简单易懂堆排序
来源:互联网 发布:全球人工智能市场规模 编辑:程序博客网 时间:2024/05/20 13:05
# 什么是堆?
1.堆是一个完全二叉树
2.任意非叶子节点的值大于等于(大顶堆)或小于等于(小顶堆)其左右孩子的值.
这就说明根元素的值是堆中最大或最小的.
如果我们输出堆顶元素, 然后对剩下的元素重新调整为一个堆, 如此直到输出所有元素, 便可完成排序了.
但是有个问题, 初始给定的数据不是一个堆啊, 所以我们要先将其初始化为堆.
因此, 实现堆排序需要解决两个问题: 1. 将一个无序序列构建为一个堆 2.输出堆顶元素后, 调整堆.
# 通常的结构
物理结构为一个数组, 逻辑结构为完全二叉树.
用 n 表示最大下标则:
array[0] 为堆顶
array[i] 的左孩子为 array[2*i+1], 右孩子为 array[2*i+2] i >= 0 && i <= (n-1)/2
# 堆排序过程
1. 怎么构建一个堆呢?
也就是说我们要将一个最大/最小的元素放到堆顶
那就在堆顶 array[0], 左子树 array[1], 右子树 array[2] 中"选择"一个最大的放到 array[0]
那左子树 array[1] 的最大元素呢? 我想聪明的你应该想到了, 继续同样的操作就行了.
这里的"选择"就是一个调整堆的过程. 所以现在我们将问题转化为调整堆了.
2. 调整堆
我们给定序列 8, 9, 6, 7, 9, 7
创建的大顶堆如下, 这时 array[0] 即为此序列的最大元素
输出堆顶元素(和序列最后一个元素交换位置)
这时就破坏了大顶堆, 我们先调整(6, 9, 7), 选择一个最大的与根交换
由于交换又破坏了左子树, 那就继续调整, 直到所以遭破坏的树调整完毕即可
有可能破坏的树只有交换后的子树.
输出堆顶元素(交换), 此时堆顶元素为序列中次大的元素
同样调整堆
继续输出
调整
交换输出
调整
交换输出, 只剩下一个元素, 此时排序完成
如此, 我们可以看出大顶堆完成是从小到大的排序
稍微想一下, 小顶堆则完成的是从大到小的排序
此时我们再看创建大顶堆的过程, 就比较清楚了. 依次队非叶子节点调整
# 代码
static void adjust_heap(int *keys, int first, int last) { int root, child; // child 开始为左孩子 for (root = first; (child = root * 2 + 1) <= last; root = child) { // 在左右孩子中选择一个最大的, 此时最大的元素下标为 child if (child + 1 < last && keys[child+1] > keys[child]) { child = child + 1; } // 如果孩子中最大的比父节点大, 则与父节点交换, 并以此孩子节点为根继续调整 root = child if (keys[child] > keys[root]) { swap(&keys[child], &keys[root]); // 如果在没交换的情况下, 父节点就是最大的, 则无需再继续调整 } else { break; } }} void heap_sort(int *keys, int len) { int i; // 使len为最大索引 len -= 1; // 构造大顶堆, 此时保证 keys[0] 为最大元素 for (i = (len-1)/ 2; i >= 0; --i) adjust_heap(keys, i, len); for (i = len; i > 0; ) { // 将 keys[0] 放到尾部, swap(&keys[i], &keys[0]); // 移除最大元素, 调整堆 adjust_heap(keys, 0, --i); } }
- 简单易懂堆排序
- 简单易懂的讲堆排序
- 单链表排序问题、简单易懂
- Dijkstra+堆优化模板 (手写堆简单易懂)
- 排序:简单排序-堆
- 快速排序算法简单易懂实现
- 快速排序算法简单易懂实现
- 简单易懂 链表冒泡排序
- 堆排序Heap Sort——浅显易懂+Java实现
- 堆排序Heap Sort——浅显易懂+Java实现
- 算法与数据结构之堆的相关知识,简单易懂。
- 堆排序简单实现
- 堆排序 简单实现
- 简单理解堆排序
- 堆排序<一> ---------简单结构堆排序
- 简单的排序---堆排序
- 简单选择排序-->堆排序
- 快速排序和冒泡排序【最简单易懂的Demo】
- 在万网虚拟主机上连接数据库出错mysqlnd cannot connect to MySQL 4.1+ using the old insecure authentication
- 黑马程序员-for remove除去相同元素
- oracle 监控函数索引
- centos下Nginx+tomcat整合安装配置
- hdu 1407 测试你是否和LTC水平一样高
- 简单易懂堆排序
- Java网络编程
- iOS 中比较俩个UIimage是否相同
- ubuntu 设置网卡为混杂模式 以及网络配置命令
- zoj 3612 Median (splay)
- 如何让快速在Mac下安装OpenCV
- 如何更改Linux yum源?
- Fortran随机整数的生成
- 补码的计算【转】