堆
堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。
下面的算法以小顶堆为例
堆的储存及其表示
可以用一维数组表示一个堆
可表示为{50,45,40,20,25,35,30,10,15}
所以可得出parent节点和左右节点的公式:
当前节点为index,
parent: (index-1)/2
left: index2+1
right: index2+2
构造堆
堆调整方法heapify()
找出以当前节点为父亲节点的树的最大节点交换其和父亲节点的位置,然后再对被换的那个节点进行递归堆调整操作
/**
* 堆调整函数
* @param array 堆
* @param parent 父亲节点
* @param len 长度
*/
public void heapify(int[] array,int parent,int len){
if(parent>=len){//最后一个节点结束
return;
}
int left = parent*2+1;
int right = parent*2+2;
int max = parent;
if(left<len && array[left]>array[max]){
max = left;
}
if(right<len && array[right]>array[max]){
max = right;
}
if(max != parent){//max节点发生变化后,递归调整max节点为parent节点的树
swap(array,max,parent);
heapify(array,max,len);
}
}
构造堆方法
从最后一个非叶子节点开始,即倒数第二层进行调用堆调整算法
/**
* 构造堆函数
* 从下往上,最后一一个非子节点开始,即倒数第二层
* @param array
* @param len
*/
public void getHeap(int[] array,int len){
int index = (len-1)/2;//获取最后一个非子节点
for(int i = index;i>=0;i--){
heapify(array,i,len);
}
}
堆排序
/**
* 堆排序算法
* 将堆顶节点与堆尾节点交换,然后隐式去除最后一个节点(通过len),并调整堆顶,heapify
* @param array
* @param len
*/
public void heapSort(int[] array,int len){
getHeap(array,len);
for(int i = len-1;i>=0;i--){
swap(array,0,i);//交换堆顶和在最后一个节点值,然后将最后一个元素从堆中去除
heapify(array,0,i);//此处len用i代替,因为len每次减一值和i等
}
}
完整代码
package sort;
public class HeapSortTest {
public void swap(int[] array,int a, int b){
int temp = array[a];
array[a] = array[b];
array[b] = temp;
}
/**
* 堆调整函数
* @param array 堆
* @param parent 父亲节点
* @param len 长度
*/
public void heapify(int[] array,int parent,int len){
if(parent>=len){//最后一个节点结束
return;
}
int left = parent*2+1;
int right = parent*2+2;
int max = parent;
if(left<len && array[left]>array[max]){
max = left;
}
if(right<len && array[right]>array[max]){
max = right;
}
if(max != parent){//max节点发生变化后,递归调整max节点为parent节点的树
swap(array,max,parent);
heapify(array,max,len);
}
}
/**
* 构造堆函数
* 从下往上,最后一一个非子节点开始,即倒数第二层
* @param array
* @param len
*/
public void getHeap(int[] array,int len){
int index = (len-1)/2;//获取最后一个非子节点
for(int i = index;i>=0;i--){
heapify(array,i,len);
}
}
/**
* 堆排序算法
* 将堆顶节点与堆尾节点交换,然后隐式去除最后一个节点(通过len),并调整堆顶,heapify
* @param array
* @param len
*/
public void heapSort(int[] array,int len){
getHeap(array,len);
for(int i = len-1;i>=0;i--){
swap(array,0,i);//交换堆顶和最后一个节点的值
heapify(array,0,i);//此处len用i代替,因为len每次减一值和i等
}
}
public static void main(String[] args) {
int[] array ={2,5,3,1,10,4};
int len =array.length;
HeapSortTest heapSortTest = new HeapSortTest();
heapSortTest.heapSort(array,len);
System.out.println("hhh");
for (int i:array){
System.out.println(i+" ");
}
}
}