Calculate Execution Times in Sort algorithm

五迷三道 提交于 2021-01-28 14:17:20

问题


I implemented Merge Sort and Quick Sort in C++, and I wanna get the execution times using each of two with many of cases those are already Sorted or not & has different size.

#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);
    }
}

int main() {
    vector<int> CaseSize(20);

    for (int i = 0; i < 10; i++) { //10 Arrays those are sorted
        CaseSize.at(i) += (i + 1) * 500;
    }

    for (int i = 10; i < 20; i++) { //rest 10 those are not sorted
        CaseSize.at(i) += (i + 1) * 5000;
    }

    cout << "------------------Sorted------------------\n\n";
    cout << "      Quick Sort       Merge Sort\n";
    for (int i = 0; i < 10; i++) {
        vector<int> Arr(CaseSize.at(i));
        Arr.front() = rand() % Arr.size();
        for (int j = 1; j < Arr.size(); j++) {
            Arr.at(j) = ((17 * Arr.at(j - 1) + 43) % (Arr.size() * 5));
        }
        vector<int> Arr2(Arr);

        sort(Arr.begin(), Arr.end());
        sort(Arr2.begin(), Arr2.end());

        cout << "N : " << CaseSize.at(i) << "    ";
        clock_t start = (int)clock();
        QuickSort(Arr, 0, Arr.size() - 1);
        printf("%0.5fms", (float)(clock() - start) / CLOCKS_PER_SEC);
        cout << "\t\t";

        clock_t start2 = (int)clock();
        MergeSort(Arr2, 0, Arr2.size() - 1);
        printf("%0.5fms", (float)(clock() - start) / CLOCKS_PER_SEC);
        cout << endl;
    }
    cout << endl;
    cout << "------------------Random------------------\n\n";
    cout << "        Quick Sort     Merge Sort\n";
    for (int k = 10; k < 20; k++) {
        vector<int> Arr(CaseSize.at(k));
        Arr.front() = rand() % Arr.size();
        for (int l = 1; l < Arr.size(); l++) {
            Arr.at(l) = ((17 * Arr.at(l - 1) + 43) % (Arr.size() * 5));
        }
        vector<int> Arr2(Arr);

        cout << "N : " << CaseSize.at(k) << "    ";

        clock_t start = (int)clock();
        QuickSort(Arr, 0, Arr.size() - 1);
        printf("%0.5fms", (float)(clock() - start) / CLOCKS_PER_SEC);

        cout << "\t\t";

        clock_t start2 = (int)clock();
        MergeSort(Arr2, 0, Arr2.size() - 1);
        printf("%0.5fms", (float)(clock() - start) / CLOCKS_PER_SEC);
        cout << endl;
    }
    return 0;
}

Well, the program worked actually, but the execution time printed was not like what I expected. Did I do all right? I wanna run both algorithms to show their execution times and so I could compare their TIME COMPLEXITY in this way (without fixing sort algorithm as much as possible).


回答1:


Your merge sort algorithm is very inefficient: Merge makes a copy of the whole array at the start of each recursive call, a quadratic cost.

The quick sort implementation is also pathologically slow in some very common cases: if the array is already sorted, the pivot value is always the smallest element in the slice, so the recursion depth is the length of the array and you get quadratic time complexity if not a stack overflow.

It is difficult to tell without measuring which if these inefficiencies will hurt performance the most, but I would guess MergeSort is the loser.

Also if you want to print milliseconds, use this expression:

printf("%0.5fms", (clock() - start) * 1000.0 / CLOCKS_PER_SEC);

To fix the problem in Merge, modify the code to create a vector of the correct size:

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

    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) {
        while (j <= high) {
            u.at(k) = s.at(j);
            j++;
            k++;
        }
    } else {
        while (i <= mid) {
            u.at(k) = s.at(i);
            i++;
            k++;
        }
    }
    for (i = low, k = 0; i <= high; i++, k++)
        s.at(i) = u.at(k);
}


来源:https://stackoverflow.com/questions/61123172/calculate-execution-times-in-sort-algorithm

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!