基本思想:
堆排序是一种树形选择排序方法,这种排序利用了堆的数据结构,是一种简单排序的改进版,将待排序的数组构造成一个大顶堆,将堆顶元素R1与最后一个元素R[n]交换,此时得到新的无序区和新的有序区,由于交换后的新的堆顶可能违反堆的性质,因此需要当前无序区调整为新堆,然后再将R1
与无序区的最后一个元素进行交换,得到新的无序区和新的有序区,重复此过程知道有序区的长度为初始数组的长度减一为止。
时间复杂度:O(nlogn),根据二叉树的特性得知
空间复杂度:O(1)
代码实现:
public class heapSort {
static int length;//用于记录数组的长度
public static int[] heap(int[] nums){
length = nums.length;
if (length ==0) return nums;
//构建一个大根堆
buildMaxHeap(nums);
//循环将堆顶(最大值)与堆尾(最小值)进行交换,删除堆尾元素,然后重新调整大根堆
while (length >0){
swap(nums,0,length-1);
length--;//原来的堆尾进入有序区,删除堆尾元素
adjustHeap(nums,0);//重新调整大根堆
}
return nums;
}
/**
* 自顶向下调整以i为根的堆为大根堆
* @param nums
* @param i
*/
public static void adjustHeap(int[] nums, int i){
//maxIndex表示最大指针
int maxIndex = i;
//如果有左子树,且左子树大于父结点,则将最大指针指向左子树
if (2 *i+1<length && nums[2*i+1]>nums[maxIndex]){
maxIndex = 2*i+1;
}
//如果有右子树,且右子树大于父结点,则将最大指针指向右子树
if (2 *i+2<length && nums[2*i+2]>nums[maxIndex]){
maxIndex = 2*i+2;
}
//如果父结点不是最大值,则将父结点与最大值交换,并且递归调整与父节点交换的位置
if (maxIndex != i){
swap(nums,maxIndex,i);
adjustHeap(nums,maxIndex);
}
}
/**
* 交换两个元素
* @param arr
* @param index1
* @param index2
*/
private static void swap(int[] arr,int index1,int index2) {
int temp = arr[index1];
arr[index1]=arr[index2];
arr[index2] = temp;
}
/**
* 自底向上构建初始大根堆
* @param arr
*/
public static void buildMaxHeap(int[] arr){
//从最后一个非叶子节点开始自底向上构造大根堆
for (int i = (length-2)/2;i>=0;i--){
adjustHeap(arr,i);
}
}
public static void main(String[] args) {
int[] arr = {70, 20, 60, 80, 30, 40, 50, 32, 64 };
System.out.println(Arrays.toString(heap(arr)));
}
}