堆排序、归并排序、快速排序总结
来源:互联网 发布:思维脑图软件 编辑:程序博客网 时间:2024/05/01 10:08
昨天刚把这三个排序算法复习了一遍,其中归并排序和快速排序特别的重要,一定要熟练并理解透彻!
以下排序的结果都默认为非递减
1、堆排序(默认大顶堆)
堆排序的思想:首先构建一个完全二叉树,从最大的非叶子结点,如果该结点小于孩子结点,则把该结点与最大的孩子结点交换,使该结点不断的往下沉到合适位置。然后又从第二大的非叶子结点开始,不断循环下去直到根节点,这时候便构造出了大顶堆,最后根结点就是堆中最大的节点。交换根结点(arc[1])与最后一个结点(arc[N--]),再使新的根节点不断往下沉到合适位置,并形成新的大顶堆,又让根结点(arc[1])与最后一个(arc[N--])交换...不断循环至整个数组有序。
看看具体的代码:
public void heapSort(int arc[]){int N =arc.length-1;for(int i=N/2;i>=1;i--){ //从最大的非叶子结点开始,构造一个大顶堆sink(arc,N,i);}while(N>=1){ each(arc,1,N--); //交换啊arc[1]与arc[N--],注意是N--而不是NSystem.out.println(arc[N+1]); //输出根结点,即堆中最大的结点sink(arc,N,1); //使新的根结点往下沉到合适的位置}}private void sink(int[] arc,int N,int i) { //使结点沉到合适的位置int j;while(2*i<=N){j = 2*i;if(arc[j]<arc[j+1]&&j<N){ //选出两个子结点中的最小值j++;}if(arc[i]>arc[j]){ //如果父结点比两个子结点都大,则跳出循环break;}each(arc,i,j); //交换父子结点i=j;}}private void each(int[] arc, int i, int j) { //两个结点交换int t;t = arc[i];arc[i] = arc[j];arc[j] = t;}
堆排序算法的几个特点:
1.时间复杂度为O(nlogn);
2.不稳定
3.适用于大量数据选出小于k(k>0)的元素
2、归并排序
归并排序思想:应用了分治思想,即不断的将大问题变小问题,通过解决小问题来解决整个大问题。
2.1自上而下的归并排序
自上而下归并排序思想:不断地将无序数组用递归方法划分为两个数组,直到数组变的很小时(如划分到每个数组只有1个元素时)再进行两两归并,最后使得整个数组有序。
看看具体的代码
public void mergeSort(int arc[],int low,int hight){int mid=low+(hight-low)/2;if(low>=hight){ //递归的结束条件return;}mergeSort(arc,low,mid); //将数组划分为两个数组mergeSort(arc,mid+1,hight);merge(arc,low,mid,hight); //将两个数组归并}private void merge(int[] arc, int low, int mid,int hight) {int a;int i=low,j=mid+1; //注意i=low,而不是i=0for(int k=low;k<=hight;k++){//k=low,而不是k=0,k<=hight,而不是k<=arc.lenght-1aux[k] = arc[k]; }for(a=low;a<=hight;a++) //a=low,而不是a=0,a<=hight,而不是a<=arc.lenght-1if(i>mid){ //如第一个数组元素全部已经归并,则将第二个数组元素直接归并到arc[]arc[a] = aux[j++]; }else if(j>hight){ //如第二个数组元素全部已经归并,则将第一个数组元素直接归并到arc[]arc[a] = aux[i++];}else if(aux[i]<aux[j]){arc[a] = aux[i++];}else{arc[a] = aux[j++];}}
注:数组aux[]声明为全局变量,如果作为局部变量的话,在递归过程中会不断实例化新的数组,这样子会增加算法的空间复杂度
2.2自下而上的归并排序
自下而上归并排序思想:直接将数组进行两两(每个数组为1个元素)归并,然后四四(每个数组为2个元素)归并,八八(每个数组为4个元素)归并,一直循环下去,直到将整个数组归并。
看看具体的代码
public void mergeSort2(int arc[]){int N = arc.length;int low;for(int sz=1;sz<N;sz*=2){for(int i=0;i<N;i+=2*sz){low = i;merge(arc,low,low+sz-1,Math.min(low+2*sz-1, N-1));}}}
注:之前一直对merge(arc,low,low+sz-1,Math.min(low+2*sz-1, N-1));中的low+sz-1和low+2*sz-1的“-1”难以理解,网上又找不到对它的解释,现在就将我的理解分享出来吧
(sz即为两两、四四、八八归并时的变量,这里不多解释)。假设a指向的元素和a左边的所有元素称为a拥有的元素,因此low+sz-1和low+2*sz-1中的 “-1”是因为low和sz或者low和2*sz拥有的元素中,low指向的那个元素重复了,既然重复那么就要-1。
归并排序算法的几个特点:
1.时间复杂度为O(nlogn);
2.稳定
3.自上而下的归并排序需要创建辅助数组
3、快速排序
快速排序的思想:找一个切点,将数组切分为两部分,小于切点的元素交换到切点的左边,大于切点的元素交换到切点的右边,并返回切点下标,再把切点左边和切点右边分别作为一个数组,递归下去,直到low>=high。
看看具体的代码
public void qSort(int arc[],int low,int high){if(low>=high){ //递归的结束条件return;}int pivot = partiton(arc,low,high); //返回切点qSort(arc,low,pivot); //将切点左边的数组作为整体递归qSort(arc,pivot+1,high); //将切点右边的数组作为整体递归}private int partiton(int[] arc, int low, int high) { //将数组切分为两部分,小于切点的元素交换到切点的左边, // 大于切点的元素交换到切点的右边,并返回切点下标int pivotkey = arc[low]; //默认数组的第一个元素为切点while(low<high){while(low<high&&arc[high]>pivotkey){high--;}ench(arc,low,high); //元素的交换while(low<high&&arc[low]<pivotkey){low++;}ench(arc,low,high);} return low; //注意返回的是下标而不是pivotkey}private void ench(int[] arc, int low, int high) { //元素的交换int t;t = arc[low];arc[low] = arc[high];arc[high] = t;}
快速排序算法的几个特点:
1.时间复杂度为O(nlogn);
2.不稳定
总结
1.堆排序适用于大量数组选出小于k(k>0)的元素的应用,过程是不断向堆尾添加数据,使新添加的不断往上浮到合适位置,并把根结点(值最大)去掉,重新调整为大顶堆,不断循环,就可以找到小于k的元素。这样大量数据就需要一次性调入内存进行排序,而是调用一部分作为堆,并不断向堆添加数据和删除不符合条件的数据。
2.归并排序分为自上而下和自下而上两种,即递归和非递归。
3.虽然快速排序和归并排序的时间复杂度都一样(nlogn),但是由于硬件原因,快速排序的平均速度要快于归并排序
- 堆排序、归并排序、快速排序总结
- 排序总结:堆排序、快速排序、归并排序、基数排序
- 归并、快速和堆排序总结
- 快速排序、希尔排序、插入排序、选择排序、归并排序、堆排序总结
- 快速排序、希尔排序、插入排序、选择排序、归并排序、堆排序总结
- 快速排序、希尔排序、插入排序、选择排序、归并排序、堆排序总结
- 排序总结(代码实现):选择排序,插入排序,归并排序,快速排序,堆排序
- 快速排序、希尔排序、插入排序、选择排序、归并排序、堆排序总结
- 快速排序、希尔排序、插入排序、选择排序、归并排序、堆排序总结
- 面试珠玑 快速排序、希尔排序、插入排序、选择排序、归并排序、堆排序总结
- 面试珠玑 快速排序、希尔排序、插入排序、选择排序、归并排序、堆排序总结
- 快速排序、堆排序、归并排序
- 快速排序、堆排序、归并排序
- 快速排序、归并排序、堆排序
- 快速排序、堆排序、归并排序
- 快速排序、堆排序、归并排序
- 归并排序、快速排序、堆排序
- 归并排序、堆排序、快速排序
- 如何在win10本地安装wordpress测试环境
- Java提高篇(二七)-----TreeMap
- 归并排序详解
- 电子邮件系统
- IPSec VPN的原理
- 堆排序、归并排序、快速排序总结
- RxJava2 源码解析(一)
- 突然自己好忙啊~
- 模!!!!!板
- Pdf File Writer 中文应用(PDF文件编写器C#类库)
- 成为专业程序员路上用到的各种优秀资料、神器及框架
- code complete学习笔记
- 关于GitHub的简单介绍
- CFRunLoop源码分析笔记