数组排序——堆排序
1、数组排序之堆排序:
堆排序利用了大根堆(或小根堆)堆顶记录的关键字最大(或最小)这一特征,使得在当前无序区中选取最大(或最小)关键字的记录变得简单。
(1)用大根堆排序的基本思想:
A:先将初始文件R[1..n]建成一个大根堆,此堆为初始的无序区。
B:再将关键字最大的记录R[1](即堆顶)和无序区的最后一个 记录R[n]交换,由此得到新的无序区R[1..n-1]和有序区R[n], 且满足R[1..n-1].keys≤R[n].key
C:由于交换后新的根R[1]可能违反堆性质,故应将当前无序区R[1..n-1]调整为堆。
D:然后再次将R[1..n-1]中关键字最大的记录R[1]和该区间的最后一个记录R[n-1]交换,由此得到新的无序区R[1..n-2]和有序区R[n-1..n],且仍满足关系R[1..n-2].keys≤R[n-1..n].keys,同样要将R[1..n-2]调整为堆。
E:直到无序区只有一个元素为止。
(2)大根堆排序算法的基本操作:
A:初始化操作:将R[1..n]构造为初始堆;
B:每一趟排序的基本操作:将当前无序区的堆顶记录R[1]和该区间的最后一个记录交换,然后将新的无序区调整为堆(亦称重建堆)。
2、代码演示
package cn.itcast_01;
public class ArraySort_heapSort {
public static void main(String[] args) {
// 定义一个数组
int[] arr = { 47, 35, 26, 26, 18, 7, 13, 19 };
// int[] arr = { 11, 3, 454, 231, 87, 334, 0, 1, 3422, 55, 10, 4324 };
// int[] arr = { 24 };
// int[] arr = {};
System.out.println("排序前:");
printArray(arr);
// 调用堆排序算法
int n = arr.length;
heapSort(arr, n - 1);
System.out.println("排序后:");
printArray(arr);
}
// 堆排序heapSort()+sift()
// 调整算法sift()
public static void sift(int r[], int k, int m) {
// 你要调整的结点是k
int i = k;
// 堆中最后一个结点的编号是m,j是i的左孩子结点
int j = 2 * i + 1;
int temp = 0;
while (j <= m) {
if (j < m && r[j] < r[j + 1])
j++;
if (r[i] > r[j])
break;
else {
temp = r[i];
r[i] = r[j];
r[j] = temp;
i = j;
j = 2 * i + 1;
}
}
}
// 堆排序heapSort()
// n是数组下标的最大值:7
public static void heapSort(int r[], int n) {
int temp = 0;
// 建立大顶堆
for (int i = n / 2; i >= 0; i--) {
sift(r, i, n);
}
// 逐步取出堆顶,再调整堆
for (int i = 0; i < n; i++) {
temp = r[0];
r[0] = r[n - i];
r[n - i] = temp;
sift(r, 0, n - i - 1);
}
}
// 数组遍历
public static void printArray(int[] arr) {
System.out.print("[");
for (int i = 0; i < arr.length; i++) {
if (i == arr.length - 1) {
System.out.print(arr[i]);
} else {
System.out.print(arr[i] + ", ");
}
}
System.out.println("]");
}
}