首页 > 代码库 > 排序算法总结
排序算法总结
相信排序算法大家都比较熟悉,这是我的个人心得以及实现,链接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),因此其速度比归并排序还要快。
另外还有一个排序神器可以参见编程珠玑,不过条件限制比较多,需要数组中的数据没有重复,输入数据限制在较小的范围内。这一问题在面试中考的比较多,对于大文件的排序非常适合,例如对于一百万个电话号码进行排序。
大概就总结这么多,第一次写博客,写的不好希望见谅。
排序算法总结