[转载]排序算法 快速排序l两种算法和堆排序(原创) – 北冥茶花开 – 博客园.
快排算法有两种 一种是算法导论里的改进的快排算法
另一种是清华那本数据结构中的古典快排算法。这里我们会看到他们在运行时间上的不同,而且古典快排竟然优于改进的快排
。呵呵 好了不多说 上代码吧 。
#include<stdio.h> #include<stdlib.h> #include<time.h> //时间计数头文件 int left(int i) { return 2*i; } int right(int i) { return 2*i+1; } void MAX_HEAPIFY(int arr[],int i,int heapsize) //调堆根函数,这名字自己YY的,基本原理就是让不合理的角色合理化, { //能力小的往下降,能力大的做老大。 int l,r; int largest; int temp; l= left(i); r=right(i); if(l<=heapsize&&arr[l]>arr[i]) //左孩子比较大那么暂记录左孩子 选他做准太子。 largest=l; else largest=i; if(r<=heapsize&&arr[r]>arr[largest]) //右孩子更有实力,选他做准太子 largest=r; if(largest!=i) //当权者arr【i】不是实力最大,则交换二者 { temp =arr[largest]; arr[largest]=arr[i]; arr[i] =temp; MAX_HEAPIFY(arr,largest,heapsize); //给以前的当权者找个归路 } } void BUILD_MAX_HEAP(int arr[],int heapsize) //建堆 { int contrasize=int (heapsize/2); //数组建堆是下标为n/2+1,...,n 是叶子节点。 for(int i=contrasize;i>=1;i--) MAX_HEAPIFY(arr,i,heapsize); } void HEAP_SORT(int arr[],int heapsize) //堆排序算法 { clock_t start=clock(); //计时开始时钟变量 double duration; //程序消耗时钟个数。 int temp; int equalsize=heapsize; BUILD_MAX_HEAP(arr,heapsize); //首建堆,但是实际上为了初始化。仔细体味能感觉到 for(int i=heapsize;i>=2;i--) { temp =arr[i]; arr[i]=arr[1]; arr[1]=temp; equalsize=equalsize-1; MAX_HEAPIFY(arr,1,equalsize); } printf("排序后的结果是:\n"); for(int i=1;i<=heapsize;i++) printf(" %d ",arr[i]); clock_t finish=clock(); duration=(double)(finish-start)/CLOCKS_PER_SEC; printf("堆排序的耗费时间为: %f\n",duration); } /*上面是堆排序,下面是快速排序的两个的版本*/ void exchange(int arr[],int i,int j) //交换数组里的两个元素,为了后面方便我故意挪出来的。 { //也算是减少内聚低耦合吧 自己都觉得自己太自恋了。 int temp; temp =arr[i]; arr[i]=arr[j]; arr[j]=temp; return ; } int partition(int arr[],int p,int r) //这是改进版的 就是圣经上的那个快排选分段标记的函数 { int contra=arr[r]; int i,j; i=p-1; for( j=p;j<=r-1;j++) //核心代码 这个实际上下面的是区别是这个固定一头,后面的小于标准 { //则往这边靠,正是这个原因导致他不如古典的快排耗时短,后面运行结果将验证 if(arr[j]<=contra) { i=i+1; exchange(arr,i,j); } } exchange(arr,i+1,r); return i+1; } int quicksort(int arr[],int p,int r) //快排函数主体 没什么好说的 { int q; if(p < r) { q=partition(arr,p,r); quicksort(arr,p,q-1); quicksort(arr,q+1,r); } return 0; } /* 上面是改进后快速排序算法,下面这个是快速排序的最早版本 实际上清华的那本什么数据结构上就这个*/ int hoarepartition(int arr[],int p,int r) //这是古典的快排 { int contra=arr[p]; int i=p; int j=r; while(true) { for(;arr[j]>contra;j--); //注意哦 有个小分号看见没? for(;arr[i]<contra;i++); //选择contra的左大与右小交换 这个是快排的核心两头动 if(i<j) exchange( arr, i, j); else return j; } } int hoarequicksort(int arr[],int p,int r) //快排主体没什么好说的 呵呵 { int q; if(p < r) { q=hoarepartition(arr,p,r); quicksort(arr,p,q-1); quicksort(arr,q+1,r); } return 0; } int initarr(int arr1[],int arr2[],int arrcol) //这个函数自己构思的 主要是为了便于后面对数组排序时 { //前一次排序算法对数组的影响不会殃及下一次别的算法对数组调用。 for(int i=1;i<=arrcol;i++) { arr1[i]=arr2[i]; } printf("排序前的数组为:\n"); for(int i=1;i<=arrcol;i++) printf(" %d ",arr1[i]); printf("\n"); return 0; } int _tmain(int argc, _TCHAR* argv[]) //主函数没什么好说的 呵呵 { time_t timer; int number; int choice; clock_t start,finish; double duration; srand((unsigned) time(&timer)); printf("请输入你想排序的的随机数个数:"); scanf("%d",&number); int *arraytest=new int[number+1]; //这个地方是为了克服VC的局限,不能申明 arraytest[0]=0; //未定义大小的数组,所以采用指针的形式先申明在转换数组 printf("待排序数组为:\n"); for(int i=1;i<=number;i++) { arraytest[i]=rand()%1000; //记得上次Cydelovy 大神给我说过随机生成,这次我就自己YY啦 printf(" %d ",arraytest[i]); } printf("\n"); int *arraycpy=new int[number+1]; for(int i=0;i<=number;i++) { arraycpy[i]=arraytest[i]; //保存数组副本。便于适合不用排序方法不影响时间。 } printf("请输入您的操作 输入CTRL+c则推出:\n"); printf("1 堆排序 2 古典快速排序 3 改进的快速排序\n"); while(scanf("%d",&choice)!=EOF) { switch(choice) { case 1: initarr(arraytest,arraycpy,number); //你永远不知道第几次进入这个case,进入前数组是什么样 HEAP_SORT(arraytest,number); //那你就有义务进行数组同一,对,不是统一。 break; case 2: //下面同了啊 不讲了啊 initarr(arraytest,arraycpy,number); start=clock(); hoarequicksort(arraytest,1,number); printf("排序后的结果是:\n"); for(int i=1;i<=number;i++) printf(" %d ",arraytest[i]); finish=clock(); duration=(double)(finish-start)/CLOCKS_PER_SEC; printf("\n古典快速排序的耗费时间为: %f\n",duration); break; case 3: initarr(arraytest,arraycpy,number); start=clock(); hoarequicksort(arraytest,1,number); printf("排序后的结果是:\n"); for(int i=1;i<=number;i++) printf(" %d ",arraytest[i]); finish=clock(); duration=(double)(finish-start)/CLOCKS_PER_SEC; printf("\n改进的快速排序的耗费时间为: %f\n",duration); break; default: printf("\n输入错误 "); break; } } return 0; }