先写个工具类:
package sort;
public class ArrayUtils {
public static void printArray(int[] array) {
System.out.print("{");
for (int i = 0; i < array.length; i++) {
System.out.print(array[i]);
if (i < array.length - 1) {
System.out.print(", ");
}
}
System.out.println("}");
}
public static void exchangeElements(int[] array, int index1, int index2) {
int temp = array[index1];
array[index1] = array[index2];
array[index2] = temp;
}
public static void printArrayByTree(int[] array) {
int mi = 1;
for (int i = 0; i < array.length; i++) {
System.out.print(array[i] + " ");
if ((i + 2) == Math.pow(2, mi)) {
System.out.println();
mi++;
}
}
System.out.println();
}
}
堆排序主要包括以下步骤:
1.构造初始化最大堆,对于数组array,从索引为half=length/2开始,到0元素,对每个元素进行沉降算法,完成后,顶元素为最大;
2.依次交换顶元素和未完成排序的数组的尾元素,此时(未完成排序数组个数减1,已完成排序数组个数加1),然后对新的顶元素进行沉降算法;直至未完成排序数组个数为1个;
沉降算法:
public static void maxheap(int array[], int heapSize, int index) {
int left = 2 * index + 1;
int right = 2 * index + 2;
int largest = index;
if (left < heapSize && array[left] > array[index]) {
largest = left;
}
if (right < heapSize && array[right] > array[largest]) {
largest = right;
}
if (index != largest) {
System.out.println("交换:" + array[index] + "和" + array[largest]);
ArrayUtils.exchangeElements(array, index, largest);
ArrayUtils.printArray(array);
ArrayUtils.printArrayByTree(array);
maxheap(array, heapSize, largest);
}
}
堆排序代码:
package sort;
public class myheapsort {
public static void main(String[] args) {
int array[] = { 2, 6, 18, 23, 5, 7, 9, 17 };
ArrayUtils.printArray(array);
ArrayUtils.printArrayByTree(array);
System.out.println("构造最大堆,从index=half开始递减使用沉降算法");
buildMaxHeap(array);
System.out.println("最大堆构造结束,接下来交换顶和末尾元素,对顶元素沉降");
for (int i = array.length - 1; i >= 1; i--) {
System.out.println("交换顶元素:" + array[0] + "和末尾元素" + array[i]);
ArrayUtils.exchangeElements(array, 0, i);
maxheap(array, i, 0);// 第一次构造完已经找出了最大顶,此时元素个数为array.length - 1
}
ArrayUtils.printArray(array);
ArrayUtils.printArrayByTree(array);
}
public static void buildMaxHeap(int array[]) {
if (array == null || array.length <= 1)
return;
int half = array.length / 2;
for (int i = half; i >= 0; i--) {
maxheap(array, array.length, i);
}
}
public static void maxheap(int array[], int heapSize, int index) {
int left = 2 * index + 1;
int right = 2 * index + 2;
int largest = index;
if (left < heapSize && array[left] > array[index]) {
largest = left;
}
if (right < heapSize && array[right] > array[largest]) {
largest = right;
}
if (index != largest) {
System.out.println("交换:" + array[index] + "和" + array[largest]);
ArrayUtils.exchangeElements(array, index, largest);
ArrayUtils.printArray(array);
ArrayUtils.printArrayByTree(array);
maxheap(array, heapSize, largest);
}
}
}
详细运行结果如下:
{2, 6, 18, 23, 5, 7, 9, 17}
2
6 18
23 5 7 9
17
构造最大堆,从index=half开始递减使用沉降算法
交换:6和23
{2, 23, 18, 6, 5, 7, 9, 17}
2
23 18
6 5 7 9
17
交换:6和17
{2, 23, 18, 17, 5, 7, 9, 6}
2
23 18
17 5 7 9
6
交换:2和23
{23, 2, 18, 17, 5, 7, 9, 6}
23
2 18
17 5 7 9
6
交换:2和17
{23, 17, 18, 2, 5, 7, 9, 6}
23
17 18
2 5 7 9
6
交换:2和6
{23, 17, 18, 6, 5, 7, 9, 2}
23
17 18
6 5 7 9
2
最大堆构造结束,接下来交换顶和末尾元素,对顶元素沉降
交换顶元素:23和末尾元素2
交换:2和18
{18, 17, 2, 6, 5, 7, 9, 23}
18
17 2
6 5 7 9
23
交换:2和9
{18, 17, 9, 6, 5, 7, 2, 23}
18
17 9
6 5 7 2
23
交换顶元素:18和末尾元素2
交换:2和17
{17, 2, 9, 6, 5, 7, 18, 23}
17
2 9
6 5 7 18
23
交换:2和6
{17, 6, 9, 2, 5, 7, 18, 23}
17
6 9
2 5 7 18
23
交换顶元素:17和末尾元素7
交换:7和9
{9, 6, 7, 2, 5, 17, 18, 23}
9
6 7
2 5 17 18
23
交换顶元素:9和末尾元素5
交换:5和7
{7, 6, 5, 2, 9, 17, 18, 23}
7
6 5
2 9 17 18
23
交换顶元素:7和末尾元素2
交换:2和6
{6, 2, 5, 7, 9, 17, 18, 23}
6
2 5
7 9 17 18
23
交换顶元素:6和末尾元素5
交换顶元素:5和末尾元素2
{2, 5, 6, 7, 9, 17, 18, 23}
2
5 6
7 9 17 18
23