排序算法五——堆排序
2017-08-09 21:02
260 查看
排序算法五:堆排序
其实堆排序本质上也是选择排序,只不过选择的方法不一样。直接选择排序法是将第一个数字与后面所有数字比较,然后找到最大(或最小)的值,然后swap交换,这样第一个数字就是最大(或最小)的数字了。然后再将第二个数与剩下的所有数字比较,找到第二大(或第二小)的数字,然后交换。就这样依次选择下去,就排好序了。那么堆排序其实跟选择排序一样,每次把最大值(或最小值)找到,找的方式是通过构建“大顶堆”或“小顶堆”来实现的,堆的最上方(树的根)一定是树的最大值(或最小值),然后将树的根与最后一个数字swap调换,然后再将剩下的数字构造为大顶堆,构建完成后再将树的根与倒数第二个数字swap调换,然后再把剩下的数字构建大顶堆,然后再调换…… 最后数字就排好序了。
根排序是不稳定的排序,因为他数字跳来跳去,换来换去。跳跃式的比较跟交换。(我知道你不知道这句话什么意思)。
这是我自己画的图,有点丑:
这个图很明显能看出,我是从0开始的,不是从1开始。
树有一个性质,就是左子树的编号是双亲编号的两倍(2*n),当然我这里编号是从0开始的,左子树的编号是双亲编号的两倍再加1(2*n + 1).
算法大概就是是先初始化大顶堆,然后再调换根与最后一个数字,然后再调整大顶堆,再调换,在调整……
你们自己看代码吧。
堆排序代码:
/***************************************************** File name:5heap_sort.c Author: Tang Zhiqian Date:2017-08-08 16:36 *****************************************************/ #include <stdio.h> #define MAX 10 typedef int ElementType; typedef ElementType ARR[MAX]; ARR arr = {10,5,1,6,2,7,3,8,4,9}; int len = sizeof(ARR)/sizeof(ElementType); void HeapSort(ARR arr); void swap(int arr[],int i,int j); void HeapAdjust(ARR arr,int s,int max); //调整为大(小)顶堆 void print(ARR arr); int main() { printf("排序前:\n"); print(arr); HeapSort(arr); printf("堆排序后:\n"); print(arr); return 0; } void HeapSort(ARR arr) { int i; for (i = (len-1)/2; i > 0; i--) //从最后一个非叶子节点开始 ★ { HeapAdjust(arr,i,len-1); } for (i = len - 1; i > 0; i--) { swap(arr,0,i); //跟最后一个调换 HeapAdjust(arr,0,i - 1); //重新调整为大顶堆 } } void HeapAdjust(ARR arr,int s,int max) { int temp = arr[s]; //记录根的值 int i; for (i = 2*s + 1; i <= max; i = 2*s + 1) //从根节点的左孩子开始往下循环 { if (arr[i + 1] > arr[i] && i < max) //如果右孩子大于左孩子,i++,i变为右孩子下标 { i++; } if (temp >= arr[i]) //如果根节点值是最大的,那就跳出循环 { break; } arr[s] = arr[i]; //到这步说明根节点不是最大的,让根节点等于大的值 s = i; //记录贡献出值的位置 } arr[s] = temp; //循环结束,把贡献出值的位置赋值temp } void swap(int arr[],int i,int j) { ElementType temp; temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } void print(ARR arr) { int i; for (i = 0; i < len; i++) { printf("%d ",arr[i]); } printf("\n"); }
我觉得代码里面注释的还比较清楚,可能只有我自己能看懂((●’◡’●))
程序运行结果:
美滋滋!没毛病!
关于堆排序的时间复杂度,平均时间复杂度O(nlogn)。他也突破了O(n^2).空间上也只用到一个temp,美滋滋!
相关文章推荐
- 堆排序、中序排序算法实现
- 排序算法复习(Java实现)(二): 归并排序,堆排序,桶式排序,基数排序
- 排序算法之堆排序
- 排序算法(五)、堆排序 —— 合并果子
- 排序算法(七) 堆排序
- Java排序算法(三):堆排序
- 选择排序、快速排序、希尔排序、堆排序不是稳定的排序算法
- 排序算法复习:直接插入排序、堆排序、快排、冒泡排序
- 排序算法之堆排序
- 排序算法(3)-堆排序
- 9种排序算法性能之比较之----堆排序
- 排序算法 快速排序 归并排序 堆排序
- Java排序算法总结之(三)——选择排序(简单选择排序、堆排序)
- 基础排序算法,java实现(快速,冒泡,选择,堆排序,插入)
- Java排序算法(二):堆排序
- 各种排序算法实现——基数排序、归并排序、插入排序、冒泡排序、选择排序、快速排序、堆排序、希尔排序
- 经典排序算法 - 堆排序Heap sort
- 排序算法(6)堆排序
- 几种常用的排序算法的分析及java实现(希尔排序,堆排序,归并排序,快速排序,选择排序,插入排序,冒泡排序)
- 排序算法之直接插入、希尔排序、堆排序三者比较