Почему время одинаковое, хотя должно возрастать (сложность O(n^2) )

Почему время одинаковое, хотя должно возрастать (сложность O(n^2) ) и как исправить?

#include <iostream>
#include <vector>
#include <random>
#include <ctime>
#include <algorithm>
#include <chrono>
#include <cstdlib>
 
using namespace std::chrono;
 
double meanTime(double* t, int n) {
    double s{0};
    for (int j{1}; j < 10; j += 1) s += t[j];
    double aTime = s / 10;
    std::cout << "\t [" << aTime << "] \t";
    
    return aTime;
}
//Измерение std для пунктов a, b и c
double stdTime(double* t, double mean) {
    double s{0};
    for (int j{1}; j < 10; j += 1) s += (t[j] - mean) * (t[j] - mean);
    double sTime = sqrt(s / 10);
    std::cout << "[" << sTime << "]";
    
    return sTime;
}
 
// a. Функция, сортирующая целые числа (int), которые размещены в векторе.
void SelectionSort(std::vector<int> &a) {
    for (int startIndex = 0; startIndex < a.size() - 1; ++startIndex)
    {
        int smallestIndex = a.at(startIndex);
        for (int currentIndex = startIndex + 1; currentIndex < a.size(); ++currentIndex)
        {
            if(a.at(currentIndex) < a.at(smallestIndex)) smallestIndex = currentIndex;
 
        }
        std::swap(a.at(startIndex), a.at(smallestIndex));
    }
}

int RandomNumber2() { return (std::rand() % 100); }

void FillVector(std::vector<int>& a) {
    std::srand(unsigned(std::time(0)));
    std::generate(a.begin(), a.end(), RandomNumber2);
}
 
double measureTime(std::vector<int>& a, int n) {
    FillVector(a);
    steady_clock::time_point t1 = steady_clock::now();
    SelectionSort(a);
    steady_clock::time_point t2 = steady_clock::now();
    duration<double> time_span = duration_cast<duration<double>>(t2 - t1);
    
    return time_span.count();
}
 
 
void Experiment(std::vector<int> &a, int n, double* means, double* stds) {
    FillVector(a);
    double* times = new double[10000];
    std::cout << "\n\nFor b: " << std::endl;
    for (int k{ 0 }; k <= 53; k++) std::cout << "-";
    
    std::cout << "\nArgument" << " | " << "Average time" << " | " << "Standard deviation of time |" << std::endl;
    for (int k{ 0 }; k <= 53; k++) std::cout << "-";
    
    for (size_t i = 1000; i < 10000; i+=1000) {
        std::cout << "\n[" << i << "]" << " ";
        
        for (size_t j = 0; j < 10; ++j) {
            times[j] = measureTime(a, i);
        }
        means[i] = meanTime(times, i);
        stds[i] = stdTime(times, means[i]);
    }
}
 
int main() {
    double* means = new double[10000];
    double* stds = new double[10000];
    int n{1000};
    std::vector<int> a(n);
    Experiment(a, n, means, stds);
    
    return 0;
}

Ответы (1 шт):

Автор решения: KoVadim

Вся проблема в том, что сортируется один и тот же массив. Поэтому и не удивительно, что время всегда одно и тоже. Не верите? Следите за руками.

Вначале в main создается вектор на 1000 элементов и отдается на сортировку

int n{1000};
std::vector<int> a(n);
Experiment(a, n, means, stds);

идем в Experiment. Там мы наполняем вектор с помощью FillVector и вызываем разные сортировки

for (size_t i = 1000; i < 10000; i+=1000) {

  for (size_t j = 0; j < 10; ++j) {
    times[j] = measureTime(a, i);

как видим, желаемый сортировочный размер передается, но массив то один и тот же и размер у него один и тот же. Что же нас ждет в measureTime?

А там мы снова наполняем вектор и сортируем его

FillVector(a);
steady_clock::time_point t1 = steady_clock::now();
SelectionSort(a);
steady_clock::time_point t2 = steady_clock::now();

Но вот только переданный размер никак не учувствует. То есть, сортируется всегда один и тот же массив. Что и совпадает с результатами эксперимента.

Кстати, функция Experiment никак не использует второй параметр n, который хранит размер.

Поэтому, переписываем main вот так

int main() {
     double* means = new double[10000];
    double* stds = new double[10000];
    int n{10000};
    std::vector<int> a(n);
     Experiment(a, means, stds);
    return 0;
}

А также поправим SelectionSort

void SelectionSort(std::vector<int> &a,int n) {
    for (int startIndex = 0; startIndex < n - 1; ++startIndex)
    {
        int smallestIndex = a.at(startIndex);
        for (int currentIndex = startIndex + 1; currentIndex < n; ++currentIndex)
        {
            if(a.at(currentIndex) < a.at(smallestIndex)) smallestIndex = currentIndex;
 
        }
        std::swap(a.at(startIndex), a.at(smallestIndex));
    }
}

Он теперь сортирует только первые n элементов. Ну и конечно позвать нужно правильно

SelectionSort(a,n);

И теперь сразу красота

Argument Average time Standard deviation of time
[1000] [0.000519672] [6.13428e-05]
[2000] [0.00196968] [0.000208873]
[3000] [0.00436231] [0.000462013]
[4000] [0.00774595] [0.000818419]
[5000] [0.0120397] [0.00127067]
[6000] [0.0172718] [0.00182428]
[7000] [0.0234652] [0.00247646]
[8000] [0.0305999] [0.00322635]
[9000] [0.0386905] [0.00408018]

В процессе чтения кода не покидало ощущение, что код написан двумя программистами совершенно разной квалификации.

→ Ссылка