堆排序算法的java实现
堆积排序(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实现的更多相关文章
- 堆排序算法 java 实现
堆排序算法 java 实现 白话经典算法系列之七 堆与堆排序 Java排序算法(三):堆排序 算法概念 堆排序(HeapSort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,可以利用数组的特 ...
- 必须知道的八大种排序算法【java实现】(三) 归并排序算法、堆排序算法详解
一.归并排序算法 基本思想: 归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的.然后再把有序子序列合并为整体有序序列. 归并 ...
- 【java排序】 归并排序算法、堆排序算法
一.归并排序算法 基本思想: 归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的.然后再把有序子序列合并为整体有序序列. 归并 ...
- 常见排序算法(附java代码)
常见排序算法与java实现 一.选择排序(SelectSort) 基本原理:对于给定的一组记录,经过第一轮比较后得到最小的记录,然后将该记录与第一个记录的位置进行交换:接着对不包括第一个记录以外的其他 ...
- 几大排序算法的Java实现
很多的面试题都问到了排序算法,中间的算法和思想比较重要,这边我选择了5种常用排序算法并用Java进行了实现.自己写一个模板已防以后面试用到.大家可以看过算法之后,自己去实现一下. 1.冒泡排序:大数向 ...
- 常见的排序算法之Java代码解释
一 简要介绍 一般排序均值的是将一个已经无序的序列数据重新排列成有序的 常见的排序分为: 1 插入类排序 主要就是对于一个已经有序的序列中,插入一个新的记录.它包括:直接插入排序,折半插入排序和希尔排 ...
- 基本排序算法的java实现
本例子实现了一些常见的排序算法,注释中也有一些关于这些算法的思想的描述,这里不做多说,直接上代码. import java.awt.List; import java.util.ArrayList; ...
- 7种基本排序算法的Java实现
7种基本排序算法的Java实现 转自我的Github 以下为7种基本排序算法的Java实现,以及复杂度和稳定性的相关信息. 以下为代码片段,完整的代码见Sort.java 插入排序 /** * 直接插 ...
- 常见排序算法总结 -- java实现
常见排序算法总结 -- java实现 排序算法可以分为两大类: 非线性时间比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此称为非线性时间比较类排序. 线性时间 ...
随机推荐
- FZU -2212 Super Mobile Charger(水题)
Problem 2212 Super Mobile Charger Accept: 1033 Submit: 1944Time Limit: 1000 mSec Memory Limit ...
- 将一个txt里的A和B谈话内容获取出来并分别保存到A和B的txt文件中
import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream;import java.io.Fi ...
- First Missing Positive -- LeetCode
Given an unsorted integer array, find the first missing positive integer. For example,Given [1,2,0] ...
- POJ2796 Feel Good(单调栈)
题意:给一个非负整数序列,求哪一段区间的权值最大,区间的权值=区间所有数的和×区间最小的数. 用单调非递减栈在O(n)计算出序列每个数作为最小值能向左和向右延伸到的位置,然后O(n)枚举每个数利用前缀 ...
- 【bzoj1415】【聪聪和可可】期望dp(记忆化搜索)+最短路
[pixiv] https://www.pixiv.net/member_illust.php?mode=medium&illust_id=57148470 Descrition 首先很明显是 ...
- 【bzoj1087】【互不侵犯King】状压dp裸题(浅尝ACM-D)
[pixiv] https://www.pixiv.net/member_illust.php?mode=medium&illust_id=54329606 向大(hei)佬(e)势力学(di ...
- 虚拟机拷贝之后,发现系统内的开机自启动的nginx,不能自启动了
因业务需要,同事以某个虚拟机为模板,复制出其他的CentOS虚拟机时,发现原系统内的开机自启动的nginx,不能再自启动了. 好吧,那就重新注册一下 nginx 的开机自启动: # 先删除原来的注册: ...
- shell中的cut命令
转:http://blog.sina.com.cn/s/blog_5e77c61f0100hqky.html cut是以每一行为一个处理对象的,这种机制和sed是一样的.(关于sed的入门文章将在近期 ...
- ASIHTTPRequest框架使用总结系列之阿堂教程3(异步请求)
在上一节中,阿堂和网友们分享了ASIHTTPRequest框架对于get,post的同步请求方式.很显然,如果网速比较慢,查询的时候会一直很黑屏,直到请求结束界面才出现结果,这样用户体验肯定很不好了. ...
- HOOK大法实现不修改程序代码给程序添加功能
[文章标题]: HOOK大法实现不修改程序代码给程序添加功能[文章作者]: 0x18c0[软件名称]: Scylla[使用工具]: OD.Stub_PE.ResHacker[版权声明]: 本文原创于0 ...