思路
堆排序分为三步:
- 首先写出如何从当前结点的树构造出最大堆的方法:max_Heap
然后把无序数组初始化成最大堆:build_Max_Heap
此时该数组组成的完全二叉树已经符合最大堆的原则了,array[0]是最大值。将第一个值和最后一个值交换,那么第一个最大的值就已经排在后面了,然后将堆长度减1。
交换后该树就不符合最大堆原则了,此时调用max_Heap再构造出最大堆。
然后再交换,把第二个最大值排在后面。
交换length-1次,直到堆长度heap-size为1,便完成了排序。图解可以查看这个链接:图解链接
代码
package com.internet.test;
import java.util.Arrays;
/**
* 堆排序,时间复杂度为O(nlogN)
*
*/
public class HeapSort {
private static int[] array;
private static int length;
private static int heap_size;
public static void sort(int[] arr){
array = arr;
length = arr.length;
heap_size = arr.length;
build_Max_Heap(arr);
swap_MaxIndex(arr);
}
//从index根节点开始构造出一个最大堆
public static void max_Heap(int[] arr,int index){
int largetIndex = index;
//因为java是从0开始的,所以左孩子结点是index*2+1,右孩子结点是index*2+2
int left = index*2+1;
int right = index*2+2;
//如果左孩子存在,则对比左孩子,选出最大值
if(left<heap_size && arr[left] > arr[index]){
largetIndex = left;
}
//如果右孩子存在,则对比右孩子,选出最大值
if(right<heap_size && arr[right]>arr[largetIndex]){
largetIndex = right;
}
//如果父结点已经最大,则无需交换了
if(largetIndex != index){
//不是最大则需要交换
swap(index, largetIndex);
//交换之后的子树会破坏最大堆原则,所以对子树进行递归
max_Heap(arr, largetIndex);
}
}
//第一次从无序的数组构造出一个最大的堆
public static void build_Max_Heap(int arr[]){
//完全二叉树中最后一个拥有子结点的树的位置是length/2-1(数组从0开始,所以也要减1)
//然后从最小树到最大树,不断构造出最大堆,直到整棵树为最大堆
System.out.println("无序数组构造成最大堆的过程是:");
for(int i=length/2-1;i>=0;i--){
max_Heap(arr, i);
System.out.println(Arrays.toString(arr));
}
}
//将第一个值和最后一个值交换,然后堆长度减1,再构造出最大堆,然后再交换,交换length-1次,直到heap-size=1
public static void swap_MaxIndex(int arr[]) {
for(int i=length;i>1;i--){
swap(0, heap_size-1);
heap_size--;
max_Heap(arr, 0);
}
}
//交换两个值
public static void swap(int a,int b){
int temp = array[a];
array[a]=array[b];
array[b]=temp;
}
public static void main(String[] args) {
int[] array = {4,1,3,2,16,9,10,14,8,7};
System.out.println("原数组为:\n"+Arrays.toString(array));
HeapSort.sort(array);
System.out.println("排序的结果是:");
System.out.println(Arrays.toString(array));
}
}
运行结果
原数组为:
[4, 1, 3, 2, 16, 9, 10, 14, 8, 7]
无序数组构造成最大堆的过程是:
[4, 1, 3, 2, 16, 9, 10, 14, 8, 7]
[4, 1, 3, 14, 16, 9, 10, 2, 8, 7]
[4, 1, 10, 14, 16, 9, 3, 2, 8, 7]
[4, 16, 10, 14, 7, 9, 3, 2, 8, 1]
[16, 14, 10, 8, 7, 9, 3, 2, 4, 1]
排序的结果是:
[1, 2, 3, 4, 7, 8, 9, 10, 14, 16]