`
alphafox
  • 浏览: 17952 次
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

快速排序,堆排序和归并排序谁更快?

 
阅读更多

时间复杂度:快速排序最坏情况只有两种,并且通过随机化算法可以避免,因此这三种算法时间复杂度可以说是一样的。

空间复杂度:快排O(logn),堆O(1),归并O(n)。

当n比较大的时候,归并排序往往会出内存溢出错误,如普通机器n>1000万时。

并且假如你能意识到cashe的存在,就能推出归并排序应该是比其他两个要慢的

关于普通快排和堆排的比较

自己写了一下代码,简单直接,没有经过什么特殊的优化,但代码也不跟其他人那样有很多没必要的东西。

import java.util.Arrays;
import java.util.Calendar;
import java.util.Random;




public class CmpQsHeap {


/**
* @param args
*/
public static void main(String[] args) {
long time =0;
int[] ary = genRandAry(1000000);
//int[] ary =new int[] {3,5,7,1,4,2,8,6,9};//实验数据,验证排序代码正确
int[] ary1 = Arrays.copyOf(ary, ary.length);//得到一个和生成的随机数组一样的数组。这样可以使两种排序使用同样的数据
int[] ary2 = Arrays.copyOf(ary, ary.length);

int low =0;
int high =ary.length-1;
long begin = Calendar.getInstance().getTimeInMillis();
Qs(ary,low,high);
long end = Calendar.getInstance().getTimeInMillis();
time = (end - begin);
// for(int i:ary){
// System.out.println(i);
// }
System.out.println(time);



time = 0;
begin = Calendar.getInstance().getTimeInMillis();
heapsort(ary1,ary1.length);
end = Calendar.getInstance().getTimeInMillis();
time = (end - begin);
// for(int i:ary1){
// System.out.println(i);
// }
System.out.println(time);



time = 0;
begin = Calendar.getInstance().getTimeInMillis();
Arrays.sort(ary2);
end = Calendar.getInstance().getTimeInMillis();
time = (end - begin);
// for(int i:ary1){
// System.out.println(i);
// }
System.out.println(time);

}

public static int[] genRandAry(int n) {
int[] ary = new int[n];
Random rand = new Random();
for (int i = 0; i < ary.length; i++) {
ary[i] = rand.nextInt();
}
return ary;
}


public static void Qs(int R[],int low, int high){
if(low<high){
int p =Partition(R,low,high);
Qs(R,low,p-1);
Qs(R,p+1,high);
}
}

private static int Partition(int[] R, int low, int high) {
int pa =R[low];
while(low<high){
while(low<high&&R[high]>=pa) --high;
R[low] =R[high];
while(low<high&&R[low]<=pa) ++low;
R[high] =R[low];
}
R[low] =pa;
return low;
}




public static void heapsort(int A[],int n) {
int i,k;
for (i=(n>>1)-1;i>= 0;i--)
shift(A,i,n);

for (i=n-1;i>=1;i--)
{
k=A[0];A[0]=A[i]; A[i]=k;
shift(A,0,i);
}
}




public static void shift(int A[] , int i , int n){
int k,t;
t=A[i]; k=(i<<1)+1;
while (k<n)
{
if ((k < n - 1) && (A[k] < A[k+1])) k++;
if (t>=A[k])
break;

A[i]=A[k];
i=k;
k=2*i+1;

}
A[i] = t;
}






}


输出

157
333
136

从上到下 依次是 普通快排,堆排,和Arrays.sort();

由结果可知普通快排所用的时间比堆排序要短将近一倍。

因为数据是随机生成的,我和你的机器可能不一样,这个数字在你跑的时候,可能会有所不同。


以下是百度中的一篇博客

http://hi.baidu.com/ycdoit/item/6b5f5b9571a843becc80e560

他提到了算法导论中说到的 对普通快排进行优化的方法也就是 Arrays.sort()中运用的。

1) 利用存储子任务的栈来消除递归

2) 利用基于三中值分区的中枢值

3) 设定一个使用切分时数组长度的最小值,如果小于这个值,就使用插入排序(这个最小值根据经验给定,一般设定为4或者5)

4) 当处理子数组的时候,首先将大的子数组压入栈中,这样可以最小化栈的总大小,确保小的问题首先被解决


但是他的结论是 堆排序比普通快排要好。(不知道是不是他的调用顺序问题,先用堆排,后用快排的话,快排就变为了O(n2))


由上述代码可知,堆排序的过程就是n次建堆的过程,

总比较次数小于2nlogn (以2为底),即比较次数比普通快排少。

建堆的代码已经相当简练,优化带来的效率提高有限。

因为不涉及到切分问题,所以能加快速度的 第3点只能用1次,而在快排中可以用多次。

堆排序是循环而非递归过程,不存在显式栈问题,而且这个循环调用函数引起了堆的变化,所以不可能提到循环外面。

循环展开和多路并发方面也不如 快排,(快排是适用分治法的,各个子问题相互独立)。

综上,快速排序最终肯定能完爆堆排序。



符: 归并

  1. private void merge(int[] a, int[] b, int[] ary) {
  2. int i = 0;
  3. int j = 0;
  4. int k = 0;
  5. while (i < a.length && j < b.length) {
  6. if (a[i] <= b[j]) {
  7. ary[k++] = a[i++];
  8. } else {
  9. ary[k++] = b[j++];
  10. }
  11. }
  12. for (; i < a.length; ++i) {
  13. ary[k++] = a[i];
  14. }
  15. for (; j < b.length; ++j) {
  16. ary[k++] = b[j];
  17. }
  18. }





分享到:
评论

相关推荐

    数据结构课程设计(排序综合)

    要求: 1)至少采用三种方法实现上述问题求解(提示,可采用的方法有插入排序、希尔排序、起泡排序、快速排序、选择排序、堆排序、归并排序)。并把排序后的结果保存在不同的文件中。 2)统计每一种排序方法的性能(以上机...

    算法第四版-PDF-网盘链接

     1.4.5 设计更快的算法 118  1.4.6 倍率实验 121  1.4.7 注意事项 123  1.4.8 处理对于输入的依赖 124  1.4.9 内存 126  1.4.10 展望 129  1.5 案例研究:union-find算法 136  1.5.1 动态...

    《算法》中文版,Robert Sedgewick,塞奇威克

    1.4.5 设计更快的算法 1.4.6 倍率实验 1.4.7 注意事项 1.4.8 处理对于输入的依赖 1.4.9 内存 1.4.10 展望 1.5 案例研究:union-find算法 1.5.1 动态连通性 1.5.2 实现 1.5.3 展望 第2章 排序 2.1 初级...

    算法,4th,塞奇威克 (Robert Sedgewick)韦恩 (Kevin Wayne), 谢路云 译.azw3

    1.4.5 设计更快的算法 1.4.6 倍率实验 1.4.7 注意事项 1.4.8 处理对于输入的依赖 1.4.9 内存 1.4.10 展望 1.5 案例研究:union—find算法 1.5.1 动态连通性 1.5.2 实现 1.5.3 展望 第2章 排序 2.1 初级...

    leetcode凑硬币-Arithmatic:算术

    概要的讲解timsort的实现以及timsort的bugs,因为是视频,所以相比论文我觉得更快看得懂,没字幕,听不懂怎么办,没事,演讲者有一个文章重新梳理视频内容 2,Tim peters自己写的论文 二维“有序数组查找” —...

    算法-第4版-完整版

    1.4.5 设计更快的算法 118 1.4.6 倍率实验 121 1.4.7 注意事项 123 1.4.8 处理对于输入的依赖 124 1.4.9 内存 126 1.4.10 展望 129 1.5 案例研究:union-find算法 136 1.5.1 动态连通性 136 ...

    算法 第4版-谢路云译-带完整书签

    1.4.5 设计更快的算法 118 1.4.6 倍率实验 121 1.4.7 注意事项 123 1.4.8 处理对于输入的依赖 124 1.4.9 内存 126 1.4.10 展望 129 1.5 案例研究:union-find算法 136 1.5.1 动态连通性 136 1.5.2 ...

    算法 第4版 高清中文版

    1.4.5 设计更快的算法 118 1.4.6 倍率实验 121 1.4.7 注意事项 123 1.4.8 处理对于输入的依赖 124 1.4.9 内存 126 1.4.10 展望 129 1.5 案例研究:union-find算法 136 1.5.1 动态连通性 136 1.5.2 实现 140 ...

    算法引论:一种创造性方法.[美]Udi Manber(带详细书签).pdf

    6.4.3 归并排序 6.4.4 快速排序 6.4.5 堆排序 6.4.6 排序问题的下界 6.5 顺序统计 6.5.1 最大数和最小数 6.5.2 查找第k小的数 6.6 数据压缩 6.7 串匹配 6.8 序列比较 6.9 概率算法 6.9.1 随机数 6.9.2 ...

    leetcode感觉难度大-CS-Interview-Prep:CS-面试-准备

    我还希望将我的代码放在一个网站上,以便于访问和更好地查看材料。 如果你有兴趣帮助这个项目,请随意实现一些未完成的数据结构或算法并提交拉取请求! 必须了解数据结构: 大批 链表 队列 堆 树 字典 / HashMap ...

    突破程序员基本功的16课.part2

    12.3.2 快速排序 12.4 插入排序 12.4.1 直接插入排序 12.4.2 折半插入排序 12.4.3 Shell排序 12.5 归并排序 12.6 桶式排序 12.7 基数排序 12.8 小结 第13课 程序开发 13.1 扎实的基本功 13.1.1 快速的...

    leetcode走方格起点到终点-leetcode:编程算法题(python解题)

     归并排序merge,双指针,用更少的辅助空间可从后往前搜索(维护三指针)  对题意因地适宜,从后往前三指针(最优) 在未排序数组中找到第k个最大元素  可构建最大堆,弹出第k个最大( 时间N*logk ); 使用快速排序...

    程序员面试刷题的书哪个好-Financial-Technology:金融科技

    alpha,您可以与市场上的大玩家建立更多的信息网络,或者您可以更快地处理数据。 我选择拿铁,我希望你们所有人都成为我旅程的一部分。 请随时做出任何贡献和反馈。 目录 平衡搜索树(一般概念,而不是细节) 遍历:...

    java 面试题 总结

    ArrayList和Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,Vector...

    C++数据抽象和问题求解(第6版).[美]Frank M. Carrano(带详细书签).pdf

    11.2.2 快速排序 312 11.2.3 基数排序 319 11.3 各种排序算法的比较 321 C++片段4 类关系和重用 325 C4.1 回顾继承 326 C4.1.1 类的公有、私有和受保护部分 331 C4.1.2 公有、私有和受保护继承 332 C4.1.3 is...

    超级有影响力霸气的Java面试题大全文档

     ArrayList 和Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,...

    易语言-高效数据结构及算法模块

    当前已支持算法:快速排序、插入排序、堆排序、归并排序、取最大、取最小、向下取整、向上取整、反转字节集、反转文本、反转数组、扩展欧几里得、中国剩余定理、快速幂、线性回归相关、线性规划 当前已支持数据结构...

    77G 22套C语言 C++ 数据结构 程序设计视频课程合集 C丨C++相关学习视频全套视频教程

    快速排序.mp4 11.归并排序.mp4 12.顺序栈.mp4 13.顺序队列.mp4 14.链表的基本概念.mp4 15.单链表的基本运算.mp4 16.循环单链表.mp4 17.双向链表.mp4 18.链式栈.mp4 19.链式队列.mp4 20.基数排序.mp4 21....

Global site tag (gtag.js) - Google Analytics