1 package com.yan.algorithm; 2 3 import java.util.Arrays; 4 5 public class HeapSortTest { 6 /* 7 * 堆得规则:任何一个parent节点都比其左右子节点大(或者小)。 8 * 堆排序步骤: 9 * 1.初始化堆,即从倒数第一个parent节点开始往前,进行调整,使任何一个parent节点都比其左右子节点大(或者小)。 10 * 2.堆初始化后的堆进行排序,每次将堆顶节点和堆最后一个节点进行交换,并调整,循环n次。 11 * 三个方法: 12 * (1)初始化 heapInit() 13 * 从倒数第一个parent节点开始往前,进行调整 14 * (2)调整 heapify() 15 * 由parent节点找到其2个子节点,并交换使得parent节点为最大,递归调整交换的子树 16 * (3)排序 sort() 17 * 每次将堆顶节点和堆最后一个节点进行交换,并调整,循环n次 18 */ 19 20 private static int[] data = new int[] { 12, 13, 14, 46, 15, 65, 99 }; 21 22 public HeapSortTest() { 23 } 24 25 public static void main(String[] args) { 26 27 heapInit(data, data.length); 28 sort(data); 29 System.out.println(Arrays.toString(data)); 30 } 31 32 /** 33 * 创建初始堆,若堆排序目的是为了递增排序,则初始堆是一个最大堆。 34 * 35 * @param data 36 * @param length为数组长度 37 */ 38 public static void heapInit(int[] data, int length) { 39 // 从最后一个parent节点开始调整。 40 int start = getParentIndex(length - 1); 41 // 因为从倒数第一个parent节点开始往前的每一个节点都要调整,所以要用for循环。 42 for (int i = start; i >= 0; i--) { 43 heapify(data, length, i); 44 } 45 } 46 47 /* 48 * 在parent和左右子节点3者之间交换调整,使得parent是3者中最大值. 49 * heapsize是需要调整的节点数的长度,用来判断子节点是否越界(和在sort方法中设置调整的范围,因为已排序的后面一部分不需要再调整了)。 50 */ 51 public static void heapify(int[] data, int heapsize, int start) { 52 int largest = start; 53 int leftChild = getLeftChildIndex(start); 54 int rightChild = getRightChildIndex(start); 55 if (leftChild < heapsize && data[largest] < data[leftChild]) { 56 largest = leftChild; 57 } 58 if (rightChild < heapsize && data[largest] < data[rightChild]) { 59 largest = rightChild; 60 } 61 /* 62 * 如果发生了交换,则该子节点的子树也不再符合堆的规则。 因此,需要继续对其子节点进行递归调整。 63 */ 64 if (largest != start) { 65 swap(data, start, largest); 66 heapify(data, heapsize, largest); 67 } 68 69 } 70 71 /** 72 * 对初始化过的堆进行排序(将最大堆排序为递增堆 “即,每次将堆顶元素和堆末尾的元素进行交换,然后从堆顶元素开始进行调整”, 73 * 或者将最小堆排序为递减堆。“即,同上”) 74 * 75 * @param data 76 */ 77 public static void sort(int[] data) { 78 for (int i = data.length - 1; i > 0; i--) { 79 swap(data, i, 0); 80 heapify(data, i, 0); 81 } 82 } 83 84 public static void swap(int[] data, int x, int y) { 85 int temp = data[x]; 86 data[x] = data[y]; 87 data[y] = temp; 88 } 89 90 public static int getLeftChildIndex(int parent) { 91 return (parent << 1) + 1; 92 } 93 94 public static int getRightChildIndex(int parent) { 95 return (parent << 1) + 2; 96 } 97 98 public static int getParentIndex(int child) { 99 return (child - 1) >> 1; 100 } 101 102 }