优化冒泡排序 - 我缺少什么?

时间:2016-10-20 16:04:43

标签: c++ algorithm sorting optimization bubble-sort

我正在尝试理解冒泡排序算法的可能优化方法。我知道有更好的排序方法,但我只是好奇。

为了测试我使用std :: chrono的效率。程序对10000个长整数数组进行30次排序并打印平均排序时间。在每次迭代中随机选取数字(最多10000个)。这是代码,没有优化:

#include <iostream>
#include <ctime>
#include <chrono>
using namespace std;



int main() {


    //bubble sort
    srand(time(NULL));

    chrono::time_point<chrono::steady_clock> start, end;

    const int n = 10000;
    int i,j, last, tests = 30,arr[n];
    long long total = 0;
    bool out;

    while (tests-->0) {


        for (i = 0; i < n; i++) {
            arr[i] = rand() % 1000;
        }


        j = n;

        start = chrono::high_resolution_clock::now();
        while(1){

            out = 0;
            for (i = 0; i < j - 1; i++) {

                if (arr[i + 1] < arr[i]) {
                    swap(arr[i + 1], arr[i]);
                    out = 1;
                }
            }

            if (!out) {
                    break;
            }

            //j--;

        }


        end = chrono::high_resolution_clock::now();

        total += chrono::duration_cast<chrono::nanoseconds>(end - start).count();
        cout << "Remaining :"<<tests << endl;

    }

    cout << "Average  :" << total / static_cast<double>(30)/1000000000<<" seconds"; // tests(30)  + nanosec -> sec


    cin.sync();
    cin.ignore();
    return 0;
}

平均排序时间为0.17秒。

如果我取消注释第47行(j--;)以避免比较已经排序的数字,我得到0.12排序时间,这是可以理解的。

如果我记得发生交换的最后一个位置,我知道在该索引之后,元素被排序,因此可以在进一步的迭代中排序到该位置。在这篇文章的第二部分中更好地解释了:https://stackoverflow.com/a/16196115/1967496。 这是实现新的可能优化的代码:

#include <iostream>
#include <ctime>
#include <chrono>
using namespace std;



int main() {


    //bubble sort
    srand(time(NULL));

    chrono::time_point<chrono::steady_clock> start, end;

    const int n = 10000;
    int i,j, last, tests = 30,arr[n];
    long long total = 0;
    bool out;

    while (tests-->0) {


        for (i = 0; i < n; i++) {
            arr[i] = rand() % 1000;
        }


        j = n;

        start = chrono::high_resolution_clock::now();
        while(1){

            out = 0;
            for (i = 0; i < j - 1; i++) {

                if (arr[i + 1] < arr[i]) {
                    swap(arr[i + 1], arr[i]);
                    out = 1;
                    last = i;
                }
            }

            if (!out) {
                    break;
            }

            j = last + 1;

        }


        end = chrono::high_resolution_clock::now();

        total += chrono::duration_cast<chrono::nanoseconds>(end - start).count();
        cout << "Remaining :"<<tests << endl;

    }

    cout << "Average  :" << total / static_cast<double>(30)/1000000000<<" seconds"; // tests(30)  + nanosec -> sec


    cin.sync();
    cin.ignore();
    return 0;
}

注意第40和48行。问题出现了:现在平均时间约为0.17秒。 我的代码中有问题,或者我错过了什么?

更新

我用10倍的数字进行排序,现在得到以下结果: 没有优化:19.3秒 第一次优化(j--):14.5秒 第二(假设)优化(j =最后+ 1):17.4秒;

根据我的理解,第二种方法在任何情况下都应该优于第一种方法,但数字会说明其他方法。

1 个答案:

答案 0 :(得分:1)

嗯......问题在于这个问题可能没有正确或错误的答案。

首先,当你只比较10000个元素时,你无法真正称它为效率测试。尝试比较更多的元素 - 可能是500000(尽管你可能需要为此动态地分配一个数组)。

其次,它可能是编译器。编译器经常尝试优化事物,以便程序执行更顺畅,更快。