复习堆排序

复习堆排序

堆的定义:

堆是一个具有以下性质的二叉树:每个结点的值都大于或者等于其左右孩子结点的值,称之为大顶堆。反之称之为小顶堆。

那么,在代码中如何表示大小顶堆?

1
2
3
arr[i]>=arr[2*i+1]&&arr[i]>=arr[2*i+2]//大顶堆

arr[i]<=arr[2*i+1]&&arr[i]<=arr[2*i+2]//小顶堆

堆排序の思想

  1. 先把待排序序列构建成一个大(小)顶堆

  2. 这时,整个序列的最大值就是堆顶的根节点(也就是数组的第一个元素)

  3. 将其与末尾元素进行交换,此时末尾就是最大值

  4. 然后将剩余的n-1个元素重新构造成一个新的堆,这样就得到n-1个元素的次小值,如此反复,就能得到一个有序序列——[重复(1),(2),(3)步骤]

代码实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import java.util.Arrays;
public class heapSort {
public static void main(String[] args){
int[] arr={25, 30, 11, 7, 22, 16, 18, 33, 40, 55};
int temp=0;
for(int i=arr.length/2-1;i>=0;i--){//从左往右,从下往上寻找非叶子节点进行初始的堆排序
adjustHeap(arr,i, arr.length);
}

for(int j=arr.length-1;j>=0;j--){//初始堆建成后,首尾的元素进行交换,此时大顶堆的结构被破坏
temp=arr[j];
arr[j]=arr[0];
arr[0]=temp;
adjustHeap(arr,0,j);//因为是首尾交换所以只有最顶部的结点不符合顶堆的定义,中间的非叶子节点均符合堆顶义,所此时的i等于0,也就是只从顶部开始调整
}
System.out.println("排序后的数组为:"+Arrays.toString(arr));
}
/**
*
* @param arr 待排序数组
* @param i 以i为父节点进行堆排序的树(数组)
* @param length 数组长度
*/
public static void adjustHeap(int[] arr,int i,int length){
int temp=arr[i];
for(int k=2*i+1;k<length;k=2*k+1){//k指向i的较大的一个子结点
if((k+1<length)&&arr[k]<arr[k+1]){//判断i叶子结点的左右结点的大小,如果左边的小于右边的,则k++
k++;
}
if(arr[k]>temp){//如果该子结点大于它的父结点,则将该子结点赋值给父节点
arr[i]=arr[k];
i=k;//以k为父节点继续和它的子节点比较
}
}
arr[i]=temp;//将最开始保存的arr[i]放到末尾
}
}