package cn.arith.zuiyou;
public class HeapSort {
/**
堆排序是稳定log(N)复杂度的算法。
堆排序需要维护的堆的性质要满足:
1.是一棵二叉树,而且是完全二叉树(除了最后一层都是满的,最后一层先把左边填满)
2.如果是最大堆,要保证父节点的值大于两个子节点的值。(最小堆同理)
二叉树的数据结构是用数组来表示的,完全二叉树的性质有 父节点坐标*2 = 左儿子坐标,
父节点坐标*2 + 1 = 右儿子坐标。
流程:
1.建立一个最大堆,让数组满足堆的性质。
2.每次取出堆顶的最大值,放到堆尾,并将堆的大小减去1,直到剩下一个元素不用排序为止。
*/
int arr[]=new int[]{9,3,6,8,2,1};
int size=arr.length;//数组长度
public static void main(String[] args) {
HeapSort s=new HeapSort();
s.sort();//数组arr从大到小排序,arr[0]最大
}
//堆排序
void sort(){
buildHeap();
int num=size;
for(int i=num-1;i>0;i--){
//交换两结点,小数往上移
swap(i,0);
size--;
swapDown(0);
}
print();
}
/**
* 建立小顶堆:父结点数字大于左右结点的数字
*/
void buildHeap(){
for(int i=size/2-1;i>=0;i--){
swapDown(i);
}
System.out.print("buildHeap:");
print();
System.out.println();
}
void print(){
for(int i=0;i<arr.length;i++){
System.out.print(" "+arr[i]);
}
}
/**
* 下滤:最大值行下沉
* @param index (带叶子结点的父结点的下标)
*/
void swapDown(int index){
System.out.print("index0="+index);
int min;//最小值指向下标
while(index*2+1<size){//如果存在左结点
System.out.print("down ");
int left=2*index+1;
min=left;
if(index*2+2<size){//如果存在右结点
int right=2*index+2;
if(arr[min]>arr[right]){
min=right;//min指向左右结点的最小值
}
}
//min与父结点index比较
if(arr[min]<arr[index]){
//交换两结点,小数往上移
swap(min,index);
index=min;
}
else{
break;
}
print();
}
System.out.println();
}
//交换两结点,小数往上移
void swap(int min,int index){
int temp=arr[min];
arr[min]=arr[index];
arr[index]=temp;
}
}