堆排序算法原理,实现及时间复杂度分析
2016-09-08 20:30
399 查看
1 堆排序
堆层次:m=log[N]
堆排序其实也是一种选择排序,是一种树形选择排序。只不过直接选择排序中,为了从R[1…n]中选择最大记录,需比较n-1次,然后从R[1…n-2]中选择最大记录需比较n-2次。事实上这n-2次比较中有很多已经在前面的n-1次比较中已经做过,而树形选择排序恰好利用树形的特点保存了部分前面的比较结果,因此可以减少比较次数。对于n个关键字序列,最坏情况下每个节点需比较log2(n)次,因此其最坏情况下时间复杂度为nlogn。堆排序为不稳定排序,不适合记录较少的排序。
运行结果如下:
别人的堆排序实现算法:
堆层次:m=log[N]
堆排序其实也是一种选择排序,是一种树形选择排序。只不过直接选择排序中,为了从R[1…n]中选择最大记录,需比较n-1次,然后从R[1…n-2]中选择最大记录需比较n-2次。事实上这n-2次比较中有很多已经在前面的n-1次比较中已经做过,而树形选择排序恰好利用树形的特点保存了部分前面的比较结果,因此可以减少比较次数。对于n个关键字序列,最坏情况下每个节点需比较log2(n)次,因此其最坏情况下时间复杂度为nlogn。堆排序为不稳定排序,不适合记录较少的排序。
#include<iostream> using namespace std; int rcount=0; int scount=0; int successchange=1; void output(int *a,int size){ for(int i=1;i<=size;i++){ cout<<a[i]<<' '; } cout<<endl; } bool judge(int i,int size){//judge if is a leaf node return i<=size/2; } bool hasRightChild(int i,int size){ return 2*i+1<=size; } bool swap(int *a,int i,int size,int*which){//which means which child is changed scount++; int q=a[i]; if(hasRightChild(i,size)){ if(q>=a[2*i]&&q>=a[2*i+1])return false; if(a[2*i]>a[2*i+1]){ a[i]=a[2*i];a[2*i]=q;*which=2*i; }else{ a[i]=a[2*i+1];a[2*i+1]=q;*which=2*i+1; } return true; }else{ if(q>=a[2*i])return false; a[i]=a[2*i];a[2*i]=q;*which=2*i;return true; } } void p(int*a,int i,int size,int time){//time means which time to adjust rcount++; int which=-1; if(judge(i,size)){ //i maybe just has one left child if(a[i]>=a[2*i]&&a[i]>=a[2*i+1]&&time!=0)return; if(hasRightChild(i,size)&&judge(2*i+1,size)){//not leaf node if(time==0){ p(a,2*i+1,size,time); }else if(a[i]<a[2*i+1]){ p(a,2*i+1,size,time); } } if(time==0){ if(judge(2*i,size))p(a,2*i,size,time);//not leaf node }else if(a[i]<a[2*i]){ if(judge(2*i,size))p(a,2*i,size,time);//not leaf node } if(swap(a,i,size,&which))p(a,which,size,time);//p(a,i,size); }else{ if(i%2==1&&!(size==1&&i==1)){//(size==1&&i==1) used to limit overflow if(ti dc57 me==0){ if(judge(i-1,size))p(a,i-1,size,time);//not a leaf node if(swap(a,(i-1)/2,size,&which))p(a,which,size,time); }else if(a[(i-1)/2]<a[i-1]){ if(judge(i-1,size))p(a,i-1,size,time);//noe a leaf node if(swap(a,(i-1)/2,size,&which))p(a,which,size,time); } } } } void workout(int *a,int size){ if(size==1)return; int n=size; int tmp=0; for(int i=0;i<n;i++,size--){ successchange=0; p(a,1,size,size!=n); tmp=a[size];a[size]=a[1];a[1]=tmp; // cout<<"this is loop "<<i<<":"; // output(a,n); } } int main(int argc,char**argv){ //int a[]={-1,16,7,3,20,17,8}; //int size=6; //int a[]={-1,2,2,4,9,3,6,7,1,5}; //int size=9; //int a[]={0,10,9,8,7,6,5,4,3,2,1}; //int size=10; //int a[]={0,1,2,3,4,5,6,7,8,9,10}; //int size=10; //int a[]={0,10,9}; //int size=2; int a[101]; for(int i=1;i<101;i++)a[i]=100-i; int size=100; cout<<"origin is:\t";output(a,size); workout(a,size); cout<<"after sort:\t";output(a,size); cout<<"recurve call count:"<<rcount<<endl; cout<<"swap call count:"<<scount<<endl; return 0; }
运行结果如下:
别人的堆排序实现算法:
/*堆排序(大顶堆) 2011.9.14*/ #include <iostream> #include<algorithm> using namespace std; int rcount=0; int scount=0; void HeapAdjust(int *a,int i,int size) //调整堆 { rcount++; int lchild=2*i; //i的左孩子节点序号 int rchild=2*i+1; //i的右孩子节点序号 int max=i; //临时变量 if(i<=size/2) //如果i不是叶节点就进行调整 { if(lchild<=size&&a[lchild]>a[max]) { max=lchild; } if(rchild<=size&&a[rchild]>a[max]) { max=rchild; } if(max!=i) { swap(a[i],a[max]);scount++; HeapAdjust(a,max,size); //避免调整之后以max为父节点的子树不是堆 } } } void BuildHeap(int *a,int size) //建立堆 { int i; for(i=size/2;i>=1;i--) //非叶节点最大序号值为size/2 { HeapAdjust(a,i,size); } } void HeapSort(int *a,int size) //堆排序 { int i; BuildHeap(a,size); for(i=size;i>=1;i--) { //cout<<a[1]<<" "; swap(a[1],a[i]); //交换堆顶和最后一个元素,即每次将剩余元素中的最大者放到最后面 //BuildHeap(a,i-1); //将余下元素重新建立为大顶堆 HeapAdjust(a,1,i-1); //重新调整堆顶节点成为大顶堆 } } int main(int argc, char *argv[]) { //int a[]={0,16,20,3,11,17,8}; int a[101]; int size=100; for(int i=1;i<=100;i++)a[i]=100-i; HeapSort(a,size); for(int i=1;i<=size;i++) cout<<a[i]<<" "; cout<<endl; cout<<"recurve count is:"<<rcount<<endl; cout<<"swap count is:"<<scount<<endl; return 0; }
相关文章推荐
- 快速排序算法原理,实现,以及时间复杂度分析
- 排序算法的C语言实现以及各个算法的时间复杂度和空间复杂度分析(冒泡排序)
- Java快速排序的实现和时间空间复杂度分析
- c语言实现线性表的建立,初始化,插入,删除,查找,遍历以及时间复杂度分析
- 找出数组中第k大的数(时间复杂度分析、C++代码实现). TopK in array. ( leetcode - 215 )
- 用不同的数据结构实现 优先队列 的时间复杂度分析
- 堆排序算法及时间复杂度分析
- 快速排序实现以及时间复杂度分析
- 对于一颗完全二叉树,要求给所有节点加上一个pNext指针,指向同一层的相邻节点;如果当前节点已经是该层的最后一个节点,则将pNext指针指向NULL;给出程序实现,并分析时间复杂度和空间复杂度。
- 排序算法——希尔排序的图解、代码实现以及时间复杂度分析
- 直接插入排序算法c语言实现。 己它的时间复杂度分析。
- 插入排序 和 归并排序(分治)的c实现和时间复杂度分析
- 插入排序算法的java实现及时间复杂度分析
- 算法 插入排序 的 JS实现及时间复杂度分析
- 对于一颗完全二叉树,要求给所有节点加上一个pNext指针,指向同一层的相邻节点;如果当前节点已经是该层的最后一个节点,则将pNext指针指向NULL;给出程序实现,并分析时间复杂度和空间复杂度。
- 算法导论-最大子数组问题-线性时间复杂度算法分析与实现
- 快速排序和冒泡排序的时间复杂度分析(C++算法实现对比)
- 插入排序和归并排序实现以及时间复杂度分析
- [置顶] 跳一跳辅助工具的原理分析,和Java实现。(其实没那么复杂)
- Python实现的堆排序算法原理与用法实例分析