【编程题】堆排序(java实现)
思路
* 第一步:时间复杂度O(n);从数组0到n建立大根堆(对于第i个元素,左孩子为left=2i+1,右孩子right=2i+2=left+1,父节点为(i-1)/2);
* 第二步:n次将大根堆顶与堆的最后一个元素交换,将堆元素减一
* 第三步:时间复杂度O(logn);重新调整堆结构,将上一步交换后的堆顶元素下沉
package sort;
import java.util.Arrays;
public class HeapSort {
public static void main(String[] args){
int[] a={4,8,1,5,3,6};
heapSort(a);
System.out.println(Arrays.toString(a));
}
/**
* 第一步:O(n)建立大根堆(对于第i个元素,左孩子为left=2*i+1,右孩子right=2*i+2=left+1,父节点为(i-1)/2);
* 第二步:n次将大根堆顶与堆的最后一个元素交换,将堆元素减一
* 第三步:O(logn)重新调整堆结构,将上一步交换后的堆顶元素下沉
* @param arr
*/
static void heapSort(int[] arr){
if(arr==null||arr.length<2)
return;
for(int i=0,len=arr.length;i<len;i++)
heapInsert(arr,i);
int heapSize=arr.length;
swap(arr,0,--heapSize);
while (heapSize>0){
heapify(arr,0,heapSize);
swap(arr,0,--heapSize);
}
}
/**
* 建堆过程,如果当前新添加的节点元素比堆顶元素大,则和堆顶元素交换,依次往上比较
* @param arr
* @param index
*/
static void heapInsert(int[] arr,int index){
while (arr[index]>arr[(index-1)/2]){//当前元素为arr[index],父元素为arr[(index-1)/2]
swap(arr,index,(index-1)/2);
index=(index-1)/2;
}
}
/**
* 下沉过程,如果堆顶元素不是最大,则将堆顶元素与左右儿子的最大值交换,依次往下比较
* @param arr
* @param index
* @param heapsize
*/
static void heapify(int[] arr,int index,int heapsize){
int left=2*index+1;//左儿子
while (left<heapsize){
int bigsize=left+1<heapsize&&arr[left]<arr[left+1]?left+1:left;//如果右儿子存在且右儿子比左儿子大,则最大值为右儿子,否则为左儿子
bigsize=arr[bigsize]>arr[index]?bigsize:index;//判断堆顶元素和左右儿子的最大值比较,取最大值
if(bigsize==index)//如果最大为当前的堆顶,退出
break;
swap(arr,bigsize,index);//否则,将当前部分堆的堆顶与最大交换
index=bigsize;//当前节点往下比较
left=2*index+1;
}
}
static void swap(int[] arr,int i,int j){
int tem=arr[i];
arr[i]=arr[j];
arr[j]=tem;
}
}