《算法与数据结构》学习笔记 4-6 优化的堆排序(原地堆排序)
来源:互联网 发布:windows官方网 编辑:程序博客网 时间:2024/06/05 08:44
《算法与数据结构》学习笔记 4-6 优化的堆排序(原地堆排序)
原地堆排序的思想
通过上一节的学习,我们知道一个数组通过 heapify ,即通过一半的元素执行 Shift Down 的操作可以逐渐地整理成一个最大堆。
于是,我们有了下面的操作:
理解这个原理的关键之处:对堆顶元素执行了 Shift Down 操作以后,就会把这个堆中的最大的元素挪到堆顶。
此时,因为用到了索引,并且须要用到索引为 0 的数组元素,因此我们就要将最大堆中数组的索引从 0 开始计算,重新写一套堆的 API。
此时,任一一个节点的下标满足下面的性质,如果它们的相应节点存在的话:
并且最后一个非叶子节点的索引是:
上面的规律,可以自己在纸上画一个完全二叉树就可以很清晰地发现。
原地堆排序的代码实现
原地堆排序的代码实现:
/** * 原地堆排序 * Created by liwei on 17/5/15. */public class HeapSort3 implements ISortAlgorithm { @Override public String getName() { return "原地堆排序"; } /** * 原地堆排序的目标就是,不再借助 MaxHeap 这个数据结构进行排序,减少了空间复杂度 * 注意:此时我们的数组索引从 0 开始定义(自己在纸上画一下图,就能清晰地明白算法实现的含义) * * @param arr 待排序数组 */ @Override public void sort(int[] arr) { int length = arr.length; // 将一个无序的数组组成了一个最大堆,第 1 个元素就是最大值 for (int i = (length - 1) / 2; i >= 0; i--) { shiftDown(arr, length, i); } // 代码逻辑非常简单明确,完全可以自己写出来 // for (int i = length - 1; i > 0; i--) { swap(arr, 0, i); shiftDown(arr, i, 0); } } /** * 从索引为 0 开始,up 为止 [0,up] 的数组元素进行 shift down 的操作 * * @param arr * @param up 这里的 up 定义为形成堆这个数据结构的最大下标(从索引 0 就放元素), * 即在区间 [0,up] 范围内 Shift Down * @param index 对索引是 index 的元素执行 Shift Down 操作 */ private void shiftDown(int[] arr, int up, int index) { // 如果有右孩子的节点,并且右孩子节点比左孩子节点的值要大 // 此时可以忽略左孩子节点的存在,拿右孩子节点的数值和自己比较 // 只要它有左孩子,就不是叶子节点,就可能 shift down,注意:这里是小于号 while (2 * index + 1 < up) { int j = 2 * index + 1; if (j + 1 < up && arr[j] < arr[j + 1]) { j = j + 1; } if (arr[index] < arr[j]) { swap(arr, index, j); index = j; // 留意 } else { break; } } } private void swap(int[] arr, int index1, int index2) { int temp = arr[index1]; arr[index1] = arr[index2]; arr[index2] = temp; }}
说明:首先进行一次 heapify 的过程:从索引为
heapify 过程的代码框架几乎是套路,一定要熟悉,只不过我们要弄清楚,我们的最大堆是从索引为 0 的位置开始存放元素,还是从索引为 1 的地方开始存放元素。
// 将一个无序的数组组成了一个最大堆,第 1 个元素就是最大值for (int i = (length - 1) / 2; i >= 0; i--) { shiftDown(arr, length, i);}
到此为止,堆的排序算法就已经介绍完了,下一节我们对之前学习过的排序算法作一个总结。
阅读全文
0 0
- 《算法与数据结构》学习笔记 4-6 优化的堆排序(原地堆排序)
- 挖掘算法中的数据结构(四):堆排序之 二叉堆(Heapify、原地堆排序优化)
- 数据结构与算法分析(Java语言描述)(13)—— 原地堆排序
- 数据结构与算法学习笔记——堆排序
- 《数据结构与算法》学习笔记27 堆排序
- 算法与数据结构学习 09 堆排序
- 数据结构与算法学习-堆排序
- 数据结构与算法:堆与堆排序
- 数据结构与算法-堆与堆排序
- 【数据结构与算法】堆排序
- 堆排序 | 数据结构与算法
- 【数据结构与算法】堆排序
- 【数据结构学习】-堆与堆排序
- 原地堆排序
- 原地堆排序
- 数据结构学习笔记 --- 排序(选择排序、堆排序)
- 数据结构学习笔记 --- 排序(选择排序、堆排序)
- 【数据结构】堆、堆排序笔记
- STM32半主机模式
- apt-get update 失败
- 代理设计模式1(知识点总结)
- HashSet如何重写了hashcode()和equals()
- Android 手机卫士(6)消息处理机制
- 《算法与数据结构》学习笔记 4-6 优化的堆排序(原地堆排序)
- oracle中单引号和双引号的作用
- Linux下Tomcat重新启动
- 安全的终止正在运行的线程
- 手写体数字识别(一)知识准备
- 《算法与数据结构》学习笔记 4-7 排序算法总结
- find查找子串位置
- 整理docker及Hadoop脚本(一)
- jQuery加载方法以及ajax的使用