1. /**
    2. * 堆排序思路:
    3. * 1.拷贝数组
    4. * 2.按i/2位置开始构造大堆或者小堆
    5. * 堆排序交换(从下往上,将大值向下交换)
    6. * 3.进行排序,将堆顶与尾标识进行交换
    7. *
    8. * 堆排序属于选择排序
    9. */
    10. public class HeapSort {
    11. public int[] sort(int[] sourceArray) {
    12. // 对 arr 进行拷贝,不改变参数内容
    13. int[] arr = Arrays.copyOf(sourceArray, sourceArray.length);
    14. // 获取数组的长度
    15. int len = arr.length;
    16. // 构造大堆
    17. buildMaxHeap(arr, len);
    18. for (int i = len - 1; i > 0; i--) {
    19. swap(arr, 0, i);//将堆顶即树根与最后一个值进行交换,即把最大值逐步往后放,来完成排序
    20. len--;
    21. heapify(arr, 0, len);//大堆位置交换
    22. }
    23. return arr;
    24. }
    25. /**
    26. * 大堆
    27. * b0
    28. * b1 b2
    29. * b3 b4 b5 b6
    30. *b7 b8 b9
    31. *
    32. * 左孩子节点下标i = 父节点下标z*2+1
    33. * 右孩子节点下标i = 父节点下标z*2+2
    34. * 进行二叉树大堆构造的时候,只需要知道最后一个节点的父节点,然后从该父节点下标往前构造即可
    35. * 最后一个节点的父节点的下标 i = length
    36. */
    37. //构建堆的时候,需要从最下层往上层排,按从小到大顺序往上排,然后将上面小的值和其子节点大的值互换位置
    38. private void buildMaxHeap(int[] arr, int len) {
    39. //节点(在数组中下标为i)
    40. //其左孩子节点下标 = 2i+1
    41. //其有孩子节点下标 = 2i+2
    42. for (int i = (int) Math.floor(len / 2); i >= 0; i--) {
    43. //从后往前,从下往上进行排序
    44. heapify(arr, i, len);
    45. }
    46. }
    47. // 判断父节点和子节点的大小关系,并进行位置交换
    48. private void heapify(int[] arr, int i, int len) {
    49. // i下标 节点位置为 父节点位置
    50. // 2*i+1 left节点位置为 左孩子节点位置
    51. // 2*i+2 right节点位置为 右孩子节点位置
    52. int left = 2 * i + 1;
    53. int right = 2 * i + 2;
    54. int largest = i;
    55. // 如果left节点下标大于等于len了,说明 i 节点是没有左孩子节点的
    56. if (left < len
    57. // 此时largest的值 = i,即父节点和左孩子节点比较大小
    58. // 如果左孩子节点大于父节点
    59. && arr[left] > arr[largest]) {
    60. // 则把以i节点为子树中的最大值确定为左孩子节点
    61. largest = left;
    62. }
    63. // 如果right节点下标大于等于len了,说明 i 节点是没有右孩子节点的
    64. if (right < len
    65. // 如果上面的if成立,则此时largest的值 为 left
    66. // 那么如果右孩子节点的值大于 largest节点即左孩子节点的值
    67. && arr[right] > arr[largest]) {
    68. // 则以i节点为子树中的最大值确定为右孩子节点
    69. largest = right;
    70. }
    71. // 如果largest发生了改变,不为 i 值,则进行位置交换
    72. if (largest != i) {
    73. swap(arr, i, largest);
    74. //发生了交换
    75. heapify(arr, largest, len);
    76. }
    77. }
    78. private void swap(int[] arr, int i, int j) {
    79. int temp = arr[i];
    80. arr[i] = arr[j];
    81. arr[j] = temp;
    82. }
    83. public void println(int [] a) {
    84. for(int x:a) {
    85. System.out.print(" "+x);
    86. }
    87. System.out.println("");
    88. }
    89. public static void main(String[] args) {
    90. HeapSort heapSortTest = new HeapSort();
    91. int[] nums = {5,9,6,8,7,3,5,10,15,22,69,36};
    92. heapSortTest.println(heapSortTest.sort(nums));
    93. }
    94. }