堆排序
基础知识:
下标为i的左孩子下标:2*i+1;
下标为i的右孩子下标:2*i+2;
下标为i的父节点下标:(i-1)/2
如何构造一个大根堆:
每一个节点和父节点做比较,如果比父节点大就交换。
public static void heapinsert(int arr[],int index){ //构造大根堆
while(arr[index]>arr[(index-1)/2]){ //节点的值比父节点值大就和父节点交换位置
swap(arr,index,(index-1)/2);
index=(index-1)/2; //下标变成父节点下标
}
}
返回大根堆的最大值,并使去掉最大值的堆扔为一个大根堆:
返回最大值后,把最后一个子结点放到根部,和比自己大的最大的子结点交换,直到下边没有子结点。
public static void heapify(int arr[],int index,int heapsize){ //可以返回大根堆的最大值,并使剩下的仍为一个大根堆
int left=2*index+1;
while(left<heapsize) { //判断下边是否还有子节点
int large = left +1< heapsize && arr[left + 1] > arr[left] ? left + 1 : left; //判断是否有右子结点,确定最大的子结点
large = arr[index] >=arr[large] ? index : large;
if(large==index){
break;
}
swap(arr, index, large);
index=large; //将最大节点下标变成当前下标
left=index*2+1;
}
}
堆排序:
另初始heapsize=数组长度,
先构造大根堆, (a)
将下标为0(即最大节点)的返回,0位置和最后一个位置的做交换,heapsize--(为了让这个最大节点和堆断开联系), (b)
(a)过程是heapinsert()过程,(b)过程是heapify()过程
重复(b)过程,直至heapsize==0。
public static void heapSort(int arr[]){
if(arr==null||arr.length<2){
return;
}
for(int i=0;i<arr.length;i++){
heapinsert(arr,i);
}
int heapsize=arr.length;
swap(arr,0,--heapsize);
while(heapsize>0){
heapify(arr,0,heapsize);
swap(arr,0,--heapsize); //将最后位置的节点和第0位置的做交换,堆的size减一,目的是让最大的节点和堆断开联系,堆的长度为0时就排好序了
}
}
swap方法:
public static void swap(int arr[],int i,int j){
int temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}