首页 > 代码库 > 排序算法总结

排序算法总结

  相信排序算法大家都比较熟悉,这是我的个人心得以及实现,链接https://github.com/yxiao1994/Sort。这里我主要说一下一些实现细节。

  对于快速排序,一定不要忘记终止条件,否则会无限制的递归导致程序崩溃,代码如下:

void Sort::QuickSort(vector<int> & vec, int p, int r) {
     if(p<r){//一定要注意这里的判断,不然会无限递归下去,另外这里是小于,不是小于等于
        int q = PARTITION(vec, p, r);//q是数组中第q-p+1大的元素
        QuickSort(vec, p, q - 1);
        QuickSort(vec, q + 1, r);
    }
}

对于归并排序,主要是归并过程的实现,需要注意设置哨兵,这一点可以参见算法导论。代码如下:

void Sort::Merge(vector<int> & vec, int p, int q, int r) {//归并排序的merge过程,参见算法导论
    int n1 = q - p + 1;
    int n2 = r - q;
    int *L = new int[n1 + 1];
    int *R = new int[n2 + 1];
    L[n1] = MAX;//设置哨兵
    R[n2] = MAX;//设置哨兵
    for (int i = 0; i < n1; i++)
        L[i] = vec[p + i];
    for (int j = 0; j < n2; j++)
        R[j] = vec[j + q + 1];
    for (int i = 0, j = 0, k = p; k <= r; k++) {
        if (L[i] <= R[j]) {
            vec[k] = L[i];
            i++;
        }
        else {
            vec[k] = R[j];
            j++;
        }
    }
    delete[]L;
    delete[]R;
}

下面是一些测试结果,这里我分为一般情况(即随机数组)和特殊情况(已排好序的数组)进行测试。我设置的数组大小是10000.

(1)一般情况下的排序性能比较

      

排序算法 冒泡排序 插入排序 快速排序 随机版本快速排序 归并排序
所需时间(单位:s) 57.516 18.538 0.083 0.087 0.075

     大家可以看到,时间复杂度为o(nlog n)的版本和时间复杂度为o(n2)的算法确实不是一个级别的。

(2)已排序数组的排序性能比较

排序算法 冒泡排序 插入排序 快速排序 随机版本快速排序 归并排序
所需时间(单位:s) 32.65 0.009 38.309 21.641 0.07

     可以看到,在已排好序的数组中,快速排序算法的性能会将至o(n2),这是因为现在每一次的划分都是将数组划分成n-1个元素的数组和1个元素的数组,而partition过程的复杂度为o(n),于是得到下式:

                                                                                                               T(n)=T(n-1)+O(n)

     这样就很容易看出为何快速排序算法的性能会下降到o(n2)级别了。采用随机版本的快速排序效果会好一些,然而根据测试效果好些并不能解决这个问题,这一点我还没有理解,希望各位赐教。而归并排序的算法依然稳定,值得注意的是此时插入排序的时间复杂度已经将为O(n),因此其速度比归并排序还要快。

     另外还有一个排序神器可以参见编程珠玑,不过条件限制比较多,需要数组中的数据没有重复,输入数据限制在较小的范围内。这一问题在面试中考的比较多,对于大文件的排序非常适合,例如对于一百万个电话号码进行排序。

     大概就总结这么多,第一次写博客,写的不好希望见谅。

 

排序算法总结