堆积排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,可以利用数组的特点快速定位指定索引的元素。堆排序是不稳定的排序方法,辅助空间为O(1), 最坏时间复杂度为O(nlog2n) ,堆排序的堆序的平均性能较接近于最坏性能。

中心思想是在使用数组存储的完全二叉树内从下往上每次构造大顶堆或者小顶堆,然后将找出来的堆顶数字放到数组结尾,剩下数组继续构造堆结构。

主要是参考了网上比较常见的两种堆排序的java实现,自己加了一些注释

实现1

采用递归,每次父节点与最大子节点交换后递归构造被交换后的子树

    public static void heapSort(int[] array) {
if (array == null || array.length <= 1) {
return;
} buildMaxHeap(array); System.out.println("buildMaxHeap " + Arrays.toString(array)); for (int i = array.length - 1; i >= 1; i--) {
exchangeElements(array, 0, i); maxHeap(array, i, 0); System.out.println("maxHeap " + Arrays.toString(array) + " i is "
+ i);
} } private static void buildMaxHeap(int[] array) {
if (array == null || array.length <= 1) {
return;
} int half = array.length / 2 - 1;
// 根据二叉树性质,深度为k的二叉树至多有2的k次方-1个结点(k≥1)
// 所以如果最末尾节点为右节点,array.length为奇数,那么上一层父节点的编号应该为(array.length-1)/2=array.length/2
// 所以如果最末尾节点为左节点,array.length为偶数,那么上一层父节点的编号也为array.length/2
// 由于数组下标从0开始,所以应该要在堆对应的编号基础上-1 // 从下往上把比较中最大的值往顶上冒,冒过后要把被换下来的值对应的子树再做一遍堆调整。
for (int i = half; i >= 0; i--) {
maxHeap(array, array.length, i);
}
} private static void maxHeap(int[] array, int heapSize, int index) {
// 堆编号x ,数组编号index ,a=index+1;
// 所以左节点数组编号=2a-1=index * 2 + 1
// 右节点数组编号=2a+1-1=index * 2 + 2 int left = index * 2 + 1;
int right = index * 2 + 2; int largest = index;
if (left < heapSize && array[left] > array[index]) {
largest = left;
} if (right < heapSize && array[right] > array[largest]) {
largest = right;
} if (index != largest) {
exchangeElements(array, index, largest);// 将子节点更大的值换到父节点 System.out.println("maxHeap " + Arrays.toString(array)
+ " index is " + index + " left is " + left + " right is "
+ right + " largest is " + largest + " heapSize is "
+ heapSize); maxHeap(array, heapSize, largest);// 原有父节点的值放到了子节点后可能不满足堆的性质,需要调整修改后largest节点对应的子树
}
} private static void exchangeElements(int[] array, int index1, int index2) {
int temp = array[index1];
array[index1] = array[index2];
array[index2] = temp;
}

实现2

while循环,同样父子节点交换后记录被换过的子节点位置,使用while (2 * k + 1 <= lastIndex)循环判断对应的子树是否符合堆性质并调整

    public static void heapSort2(int[] array) {
for (int i = 0; i < array.length; i++) {
maxHeap2(array, array.length - 1 - i);
exchangeElements(array, 0, array.length - 1 - i);
System.out.println(Arrays.toString(array));
} } private static void exchangeElements(int[] array, int index1, int index2) {
int temp = array[index1];
array[index1] = array[index2];
array[index2] = temp;
} private static void maxHeap2(int[] data, int lastIndex) { //lastIndex= array.length - 1
//所以(lastIndex+1)/2-1等于上层最后一个有子节点的节点在数组中的索引
//(lastIndex+1)/2-1=(lastIndex-1)/2
for (int i = (lastIndex - 1) / 2; i >= 0; i--) {
// 保存当前正在判断的节点
int k = i; // 若当前节点的左节点存在
while (2 * k + 1 <= lastIndex) {// // biggerIndex总是记录较大节点的值,先赋值为当前判断节点的左子节点
int biggerIndex = 2 * k + 1;
if (biggerIndex < lastIndex) {
// 若右子节点存在,比较左右子节点大小,右节点不存在biggerIndex为左节点
if (data[biggerIndex] < data[biggerIndex + 1]) {
// 若右子节点值比左子节点值大,则biggerIndex记录的是右子节点的值
biggerIndex++;
}
}
if (data[k] < data[biggerIndex]) {
// 若当前节点值比子节点最大值小,则交换2者得值,交换后将biggerIndex值赋值给k
exchangeElements(data, k, biggerIndex);
k = biggerIndex; //k记录了原来的父节点被换到了什么位置,原来的父节点下来后不一定比子节点更大
//while循环继续去判断它对应的子树符不符合堆的性质并调整
System.out.println("k is "+k+" "+Arrays.toString(data)); } else {
//父节点已经比子节点大了,不需要调整
break;
} //System.out.println();
}
} }

参考资料

http://blog.csdn.net/apei830/article/details/6584645

http://blog.csdn.net/kimylrong/article/details/17150475

堆排序算法的java实现的更多相关文章

  1. 堆排序算法 java 实现

    堆排序算法 java 实现 白话经典算法系列之七 堆与堆排序 Java排序算法(三):堆排序 算法概念 堆排序(HeapSort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,可以利用数组的特 ...

  2. 必须知道的八大种排序算法【java实现】(三) 归并排序算法、堆排序算法详解

    一.归并排序算法 基本思想: 归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的.然后再把有序子序列合并为整体有序序列. 归并 ...

  3. 【java排序】 归并排序算法、堆排序算法

    一.归并排序算法 基本思想: 归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的.然后再把有序子序列合并为整体有序序列. 归并 ...

  4. 常见排序算法(附java代码)

    常见排序算法与java实现 一.选择排序(SelectSort) 基本原理:对于给定的一组记录,经过第一轮比较后得到最小的记录,然后将该记录与第一个记录的位置进行交换:接着对不包括第一个记录以外的其他 ...

  5. 几大排序算法的Java实现

    很多的面试题都问到了排序算法,中间的算法和思想比较重要,这边我选择了5种常用排序算法并用Java进行了实现.自己写一个模板已防以后面试用到.大家可以看过算法之后,自己去实现一下. 1.冒泡排序:大数向 ...

  6. 常见的排序算法之Java代码解释

    一 简要介绍 一般排序均值的是将一个已经无序的序列数据重新排列成有序的 常见的排序分为: 1 插入类排序 主要就是对于一个已经有序的序列中,插入一个新的记录.它包括:直接插入排序,折半插入排序和希尔排 ...

  7. 基本排序算法的java实现

    本例子实现了一些常见的排序算法,注释中也有一些关于这些算法的思想的描述,这里不做多说,直接上代码. import java.awt.List; import java.util.ArrayList; ...

  8. 7种基本排序算法的Java实现

    7种基本排序算法的Java实现 转自我的Github 以下为7种基本排序算法的Java实现,以及复杂度和稳定性的相关信息. 以下为代码片段,完整的代码见Sort.java 插入排序 /** * 直接插 ...

  9. 常见排序算法总结 -- java实现

    常见排序算法总结 -- java实现 排序算法可以分为两大类: 非线性时间比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此称为非线性时间比较类排序. 线性时间 ...

随机推荐

  1. 后门构建工具Backdoor Factory

    后门构建工具Backdoor Factory   在渗透测试中,后门程序帮助渗透测试人员在目标机器上执行各种预期的操作.例如,它可以建立从目标主机到攻击机的网络连接,方便渗透测试人员控制目标主机.Ka ...

  2. SQLite中的内连接简化技巧

    SQLite中的内连接简化技巧   在SQLite中,通过内连接可以将两个表通过条件表达式关联起来,构成一个新记录集或视图.形式如下:   SELECT ... FROM t1 JOIN t2 ON ...

  3. List集合-保存和输出宠物信息

    package collection; /** * 宠物类 * @author * */ public class Pet { private String name; private String ...

  4. Android TextView 阴影效果(投影)

    Android TextView 阴影效果(投影) 四个参数: 1 2 3 4 android:shadowColor="@color/white" android:shadowD ...

  5. 【MySQL】undo,redo,2PC,恢复思维导图

    http://blog.itpub.net/22664653/viewspace-2131353/

  6. MySQL性能指标及计算方法 等待show processlist

    http://www.cnblogs.com/cyt1153/p/6697847.html http://www.cnblogs.com/cyt1153/tag/mysql/

  7. Gradle Distributions

    Gradle Distributions services.gradle.org/ distributions/ gradle-3.4-rc-3-all.zip 13-Feb-2017 14:55 + ...

  8. python的几个概念

    1.函数在传递实参的时候是传递的是引用而不是从内存中重新赋相同值给形参. 2.函数名带圆括号和不带圆括号.函数名带圆括号是函数的调用,而函数名代表的是函数体. 3.函数返回值,在函数没有返回值的时候默 ...

  9. ios开发中APP底部上滑不能调出如WiFi、蓝牙、播放等的设置页面的解决的方法

    在开发的APP中我们通常通过手动底部上滑来调出WiFi.蓝牙.飞行模式等的设置页面.有时我们开发的APP无法调出. 解决的方法: 进入iPhone "设置" --> &quo ...

  10. ELKStack日志离线系统

    通过Filebeat抽取数据到logstash中,转存到ElasticSearch中,最后通过Kibana进行展示 https://www.ibm.com/developerworks/cn/open ...