堆排序
来源:互联网 发布:linux mint 18安装 编辑:程序博客网 时间:2024/05/16 03:04
堆排序
前言
堆排序和归并排序一样,时间复杂度都是O(nlg(n)),和插入排序相同的是具有空间的原址性:任何时候都只需要常数个额外的空间元素存储临时数据。因此堆排序可以说是结合了之前讨论的两种排序算法的优点。
(二叉)堆又是一个数组,它可以被堪称一个近似的完全二叉树,树上的每一个节点都对应着数组中的一个元素。从图中可以看到,除了叶节点之外,该树是完全充满的,而且是从左向右的填充。很容易就能够通过一个节点得到其父节点,左孩子和右孩子。
再利用数学归纳法稍加证明,则能够得到下面的结论:对于一个堆a[n]来说,从a[n/2]到a[n]均为叶节点,a[0]到a[n/2-1]的都为根节点。
堆排序原理
最大堆是用来实现堆排序的先决条件,最大堆的概念:在最大堆中,一个节点的值小于等于其父节点的值。,最小堆的概念则正好相反,这里不再赘述。
那么这个最大堆最上面的一个根节点即整个数组最大的节点,利用这一特性即可进行排序,将最大的那个节点和位于堆最后的一个节点值交换,整个数组最大的数就移动到了堆的最后。
在交换了之后会出现最大堆被破坏的问题,因此每次提取最大值后需要对其a[0~n-1]子堆进行维护,即最大堆维护。提取一次,维护一次,直到子堆缩小成一个元素,这时整个堆呈升序排列。
最大堆维护:维护最大堆即针对某一结点来对堆进行调整,使堆呈现最大堆的特性。对于一个节点i,假设其左孩子为left(i),右孩子为right(i),则需要找出a[i],a[left(i)],a[right(i)]中最大值的下标,并记录这个下标为max_index,如果max_index==i,则以i为根节点的树呈最大堆状态,不必理会,否则就将a[max_index]与a[i]交换,再以max_index作为根节点,一直递归查找下去,将下面的子树都调整为最大堆状态。
C语言的实现
//针对节点i进行最大堆的调整void max_heapify(int* a, int i, int count){ int left_index , right_index ; int max_index = i; left_index = 2 * i + 1; right_index = left_index + 1; if ((left_index <= count) && (a[left_index] > a[max_index])) max_index = left_index; if ((right_index <= count) && (a[right_index] > a[max_index])) max_index = right_index; if (max_index != i) { int t = a[i]; a[i] = a[max_index]; a[max_index] = t; max_heapify(a, max_index, count); }}//建立最大堆void build_max_heap(int* a, int count){for (int i = count / 2; i >= 0; i--) { //对每个子根节点进行堆调整 max_heapify(a, i, count); }}//开始堆排序void heap_sort(int* a, int count){ int t; for (int i = count; i >= 1; i--) { t = a[0]; a[0] = a[i]; a[i] = t; max_heapify(a, 0, i - 1); }}void main(){ int count, *p; printf("请输入需要排序的数的个数 :"); scanf_s("%d", &count); p = (int *)malloc(count * 2); printf("\n请输入需要排序的%d个数字:",count); for (int i = 0; i < count; i++) { scanf_s("%d", p+i); } //依据输入的一列数字,建出一个最大堆 build_max_heap(p, count - 1); printf("建立最大堆后的数组:"); for (int i = 0; i < count; i++) { printf("%d ", p[i]); } printf("\n\n"); //开始堆排序 heap_sort(p, count - 1); printf("堆排序后的数组:"); for (int i = 0; i < count; i++) { printf("%d ", p[i]); } printf("\n\n"); system("pause");}
- 堆及堆排序
- 堆/堆排序特点
- 【二叉堆、堆排序】
- 二叉堆 & 堆排序
- 二叉堆 & 堆排序
- 堆与堆排序
- 堆与堆排序
- 堆与堆排序
- 堆与堆排序
- 堆与堆排序
- 堆与堆排序
- 堆和堆排序
- 堆排序(最大堆)
- 堆和堆排序
- 堆和堆排序
- 堆及堆排序
- 堆和堆排序
- 堆与堆排序
- 什么叫闭包
- 文本相似度算法(余弦定理)
- extern "c"
- PATBasic——1011. A+B和C (15)
- monoid之含义
- 堆排序
- 6.22 比较大小 oj 洗刷刷 1
- linux命令df
- Android数据存储
- html小知识
- Linux SPI总线和设备驱动架构之三:SPI控制器驱动
- 30分钟让你懂得正则表达式
- c++操作符重载
- Leetcode#12 Integer to Roman