堆排序-java
2016-02-22 20:40
323 查看
堆排序-java
转载请注明出处:http://blog.csdn.net/a740169405/article/details/50718944思想:
前面的文章有选择排序,我们每次都要从剩余的数组中找出最小值,这样每次比较都会有重复的操作。
如果我们能记录下最小的值,将提高选择效率,从而提高算法的效率。
堆排序把待排序的数组转化为完全二叉树的结构,并按照层级关系对每个节点赋值下标。
其中涉及到了大顶堆和小顶堆的概念,即
完全二叉树的双亲节点与孩子之间的下标存在关系:如果结点i = 0,则其无双亲,如果i > 1,
则其双亲为:
堆排序不断的将二叉树变成大顶堆,然后将根节点和末尾节点交换,接着继续将二叉树变成大顶堆,
如此往复,直到排序完成。
循环方式实现:
/** * 堆排序 */ private static void heepSort(int[] arr) { int i; for (i = arr.length / 2; i >= 0; i--) { // 之所以从中间到最小,是因为中间到最小这些下标都不是叶子节点 heapAdjust(arr, i, arr.length - 1); } for (i = arr.length - 1; i > 0; i--) { // 交换根节点与末尾元素互换 swap(arr, 0, i); // 重新调整大顶堆 heapAdjust(arr, 0, i - 1); } }
这里有一个方法,就是heapAdjust方法,它是用来把当前数组排成大顶堆的方法:
private static void heapAdjust(int[] arr, int i, int count) { int tmp = arr[i]; // 先把双亲节点记录下来 for (int j = i * 2; j <= count; j*=2) { // 每次跳跃的值为2j,原因是完全二叉树中,(双亲节点下标 = 左孩子 * 2) if (j <= count - 1 && arr[j + 1] > arr[j]) { // 当右孩子比左孩子大时,需要把下标移到右孩子那 ++j; } if (arr[j] <= tmp) { // 如果两个孩子中最大的那个都比双亲节点小,则此次不做调整 break; } // 把较大的那个孩子和双亲节点对换 arr[i] = arr[j]; // 把i赋值成较大的那个孩子的下标,让循环结束后双亲节点跑到下面去 i = j; } // 移动(也有可能不移动)双亲节点到下面 arr[i] = tmp; }
还有一个交换方法:
private static void swap(int[] arr, int l, int r) { int tmp = arr[l]; arr[l] = arr[r]; arr[r] = tmp; }
调用方法:
int[] arr = new int[] {1, 45, 78, 23, 12, 98, 150, 1, 45}; heepSort(arr); System.out.println(Arrays.toString(arr));
结果:
复杂度分析:
稳定性分析:
由于堆排序是跳跃式交换数据,所以是不稳定的算法
参考:《大话数据结构》书籍
相关文章推荐
- Java
- Java IO 之File类
- HDU Exponentiation 1063 Java大数题解
- Java-final
- LeetCode29DivideTwoIntegers--In Java
- Spring.Net学习笔记(二)-数据访问器
- java中静态代码块的用法 static用法详解
- Spring源代码解析 ---- 循环依赖
- Android开发遇到eclipse运行程序时报timeout
- 【转】一个不错的eclipse反编译插件
- 第一个Java程序——HolloWorld
- Java多线程Lock对象之ReentrantLock(1)
- java 以行为单位读取txt文件(1)
- Java多线程数量再次说明
- Java语言实现大数字乘除
- Spring中常用类型的bean配置(Map,List,Set,基本类型)
- 使用Java VisualVM监控远程JVM
- java编译器API——使用编译工具
- Java游戏编程原理与实践教程
- 华为机试题: 用小数形式输出指定符号出现的频率(java)