非递归方法的堆排序实现
2014-09-03 16:50
148 查看
引言
首先需要明确,如何根据父亲结点的位置得知孩子结点的位置,以及如何根据孩子结点的位置得知父亲结点的位置。假设数列索引从0开始,如果父亲结点的索引为i,那么左孩子索引为2i+1,右孩子索引为2i+2;如果孩子结点的索引为j,那么父亲结点的索引为(j-1)/2。
堆排序的核心在于函数voidadjustdown(int*arr,inti,intend),其中第i+1个元素到最后一个元素均已满足堆结构,每次adjustdown可以使当前位置i的元素也满足堆结构。如果是大堆,则经过adjustdown后当前位置的元素最大;如果是小堆,则经过adjustdown后当前位置的元素最小。
以下代码,将数列从小到大排序。采用大堆,并且使用了非递归的方法。函数adjustdown中的五个if语句实际上有一部分是可以合并的,但是为了逻辑清晰,在本代码中,完整保留下来了。注释我写的很用心,相信读者可以看懂。
代码
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<time.h> staticvoidshow(int*arr,intlen) { intindex; for(index=0;index<len;index++) { printf("%d",arr[index]); } printf("\n"); } staticvoidswap(int*left,int*right) { inttmp=*left; *left=*right; *right=tmp; } voidadjustdown(int*arr,inti,intend) { intkey=arr[i]; intp=i; intleft=2*p+1; /*越界就是没孩子*//*只要能进循环,一定有左孩子*/ while(left<=end) { /*有右孩子的情况下,大于等于左右孩子不用换*/ if((key>=arr[left])&&(left+1<=end&&key>=arr[left+1])) { break; }elseif(key>=arr[left]&&left+1>end)/*没有右孩子,只有左孩子,且大于等于左孩子不用换*/ { break; }elseif(left+1<=end&&arr[left+1]>=arr[left]&&key<arr[left+1])/*与右孩子换。要保证有右孩子,且右孩子大于等于左孩子,父亲小于右孩子*/ { swap(arr+p,arr+left+1); p=left+1;//父亲与谁换,就到谁的位置了 left=2*p+1;//父亲新的左孩子的位置 }elseif(left+1<=end&&arr[left]>arr[left+1]&&key<arr[left])/*与左孩子换。有右孩子的情况下,右孩子小于左孩子,父亲小于左孩子*/ { swap(arr+p,arr+left); p=left; left=2*p+1; }elseif(left+1>end&&arr[left]>key)/*与左孩子换。没右孩子的情况下,只需父亲小于左孩子*/ { swap(arr+p,arr+left); p=left; left=2*p+1; } } } voidheap_sort(int*arr,intlen) { intp;//最后一个父亲 intend;//最后一个有效下标 /*建一个大顶堆,从最后一个父亲开始调*/ for(p=(len-1-1)/2;p>=0;p--) { adjustdown(arr,p,len-1); } /*根结点的值最大,与末尾交换,并继续建立堆结构,再交换...*/ for(end=len-1;end>=1;end--) { swap(arr,arr+end);//end已经是最大值 adjustdown(arr,0,end-1);//从arr+1到end-1位置都是满足堆结构的 } } intmain(intargc,char*argv[]) { intindex; intarr[10]; memset(arr,0,10); srand(time(NULL)); for(index=0;index<10;index++) { arr[index]=rand()%20+1; } show(arr,10); heap_sort(arr,10); show(arr,10); system("pause"); return0; }
相关文章推荐
- 非递归方法的堆排序实现
- C#纯数学方法递归实现货币数字转换中文
- C#纯数学方法递归实现货币数字转换中文
- 使用递归的方法去实现一棵树
- 用递归的方法实现 n 的阶乘,4399笔试题,请指教
- [整理]二分查找搜索算法原理及递归,迭代方法实现
- STL学习笔记:用非递归的方法实现汉诺塔问题
- 用递归方法实现指定目录的枚举——兼谈File类的使用
- [转]树结构表递归查询在ORACLE和MSSQL中的实现方法
- 二叉树的遍历方法及递归实现
- 递归实现遍历文件夹的两种方法
- [转]C#纯数学方法递归实现货币数字转换中文
- C#2.0纯数学方法递归实现货币数字转换中文
- 树结构表递归查询在ORACLE和MSSQL中的实现方法 [续]
- C#纯数学方法递归实现货币数字转换中文
- asp.net无限级分类递归实现方法二
- 递归方法实现二叉树的创建,遍历
- 递归实现与实现转换数据的方法
- 用非递归方式实现二叉树的前、中、后三种遍历方法
- 用递归方法实现读取文件夹下所有文件信息