Сравнение времени выполнения со сложностью времени в слиянии и быстрой сортировке - PullRequest
1 голос
/ 10 апреля 2020

Я реализовал Merge & Quick Sort в учебнике, который я выучил, и он говорит, что Сложности Времени каждого рода выглядят так: Merge Sort: O (n.log (n)) / Быстрая сортировка: средняя O (n.log (n)) и O (n 2 ) в худшем случае (если отсортирован массив ключей).

Итак, я выполнил программы с двумя типами массивов: отсортированными и случайными, с разными размерами.

Поскольку я хотел получить среднее время, я пробовал 10 раз для каждого случая.

Вот код слияния и быстрой сортировки:

#include <iostream>
#include <ctime>
#include <vector>
#include <algorithm>

using namespace std;

void Merge(vector<int>& s, int low, int mid, int high) {
    int i = low;
    int j = mid + 1;
    int k = low;
    vector<int> u(s);

    while (i <= mid && j <= high) {
        if (s.at(i) < s.at(j)) {
            u.at(k) = s.at(i);
            i++;
        } else {
            u.at(k) = s.at(j);
            j++;
        }
        k++;
    }
    if (i > mid) {
        for (int a = j; a < high + 1; a++) {
            u.at(k) = s.at(a);
            k++;
        }
    } else {
        for (int a = i; a < mid + 1; a++) {
            u.at(k) = s.at(a);
            k++;
        }
    }
    for (int a = low; a < high + 1; a++)
        s.at(a) = u.at(a);
}
void MergeSort(vector<int>& s, int low, int high) {
    int mid;
    if (low < high) {
        mid = (low + high) / 2;
        MergeSort(s, low, mid);
        MergeSort(s, mid + 1, high);
        Merge(s, low, mid, high);
    }
}

void swap(int& a, int& b) {
    int tmp = a;
    a = b;
    b = tmp;
}
void Partition(vector<int>& s, int low, int high, int& pvpoint) {
    int j;
    int pvitem;

    pvitem = s.at(low);
    j = low;
    for (int i = low + 1; i <= high; i++) {
        if (s.at(i) < pvitem) {
            j++;
            swap(s.at(i), s.at(j));
        }
        pvpoint = j;
        swap(s.at(low), s.at(pvpoint));
    }
}

void QuickSort(vector<int>& s, int low, int high) {
    int pvpoint;
    if (high > low) {
        Partition(s, low, high, pvpoint);
        QuickSort(s, low, pvpoint - 1);
        QuickSort(s, pvpoint + 1, high);
    }
}

И каждая из этих функций main () печатает время выполнения в массивах SORTED и RANDOM. Вы можете увидеть результат, добавив одну из этих основных функций в Visual Studio (C ++):

//Sorted key array
int main() {
    int s;
    for (int i = 1; i < 21; i++) { //Size is from 300 to 6000
        s = i * 300;
        vector<int> Arr(s);
        cout << "N : " << s << "\n";

        //Assign Random numbers to each elements
        Arr.front() = rand() % Arr.size();
        for (int j = 1; j < Arr.size(); j++) { Arr.at(j) = ((737 * Arr.at(j - 1) + 149) % (Arr.size() * 5)); }
        sort(Arr.begin(), Arr.end());

        //QuickSort(Arr, 0, Arr.size() - 1);  <- you can switch using this instead of MergeSort(...) below
        for (int i = 0; i < 10; i++) { //print 10 times of execution time
            clock_t start, end;
            start = clock();
            MergeSort(Arr, 0, Arr.size() - 1);
            end = clock() - start;
            printf("%12.3f  ", (double)end * 1000.0 / CLOCKS_PER_SEC);
        }
        cout << endl;
    }
    return 0;
}

//Random key array
int main() {
    int s;
    for (int i = 1; i < 21; i++) {
        s = i * 3000;
        vector<int> Arr(s);
        cout << "N : " << s << "\n";
        for (int i = 0; i < 10; i++) {
            //Assign Random numbers to each elements
            Arr.front() = rand() % Arr.size();
            for (int j = 1; j < Arr.size(); j++) { Arr.at(j) = ((737 * Arr.at(j - 1) + 149) % (Arr.size() * 5)); }

            //QuickSort(Arr, 0, Arr.size() - 1);  <- you can switch using this instead of MergeSort(...) below
            clock_t start, end;
            start = clock();
            MergeSort(Arr, 0, Arr.size() - 1);
            end = clock() - start;
            printf("%12.3f  ", (double)end * 1000.0 / CLOCKS_PER_SEC);
        }
        cout << endl;
    }
    return 0;
}

И, в общем, результат не соответствует их временной сложности. например, сортировка слиянием (RANDOM Array) размер N = 3000 отпечатков за 20 мс, но размер N = 60000 отпечатков 1400 ~ 1600 мс !! он должен печатать почти 400 мс, потому что сложность по времени (не в худшем случае) в быстрой сортировке составляет O (n.log (n)) , не так ли? Я хочу знать, что влияет на это время и как я могу увидеть напечатанное время, которое я ожидал.

1 Ответ

0 голосов
/ 10 апреля 2020

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

Ваша функция MergeSort имеет недостаток: вы продублируйте массив целом в merge, что приведет к значительным затратам времени и квадратичной сложности c времени. Это невинно выглядящее определение: vector<int> u(s); определяет u как вектор, инициализированный как копия s, полный массив .

C ++ - очень мощный язык, часто слишком мощный , заваленные ловушками и ловушками, такими как эта. Это очень хорошая вещь, которую вы пытались проверить, соответствует ли ваша программа ожидаемой производительности по известной временной сложности алгоритма. Такое беспокойство, увы, слишком редко.

...