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 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | package bobo.algo; import java.util.*; // 不使用一个额外的最大堆, 直接在原数组上进行原地的堆排序 public class HeapSort { // 我们的算法类不允许产生任何实例 private HeapSort(){} public static void sort(Comparable[] arr){ int n = arr.length; // 注意,此时我们的堆是从0开始索引的 // 从(最后一个元素的索引-1)/2开始,为什么要除以2? // 最后一个元素的索引 = n-1 //这个for的作用是什么? for ( int i = (n- 1 - 1 )/ 2 ; i >= 0 ; i -- ) shiftDown2(arr, n, i); for ( int i = n- 1 ; i > 0 ; i-- ){ swap( arr, 0 , i); shiftDown2(arr, i, 0 ); } } // 交换堆中索引为i和j的两个元素 private static void swap(Object[] arr, int i, int j){ Object t = arr[i]; arr[i] = arr[j]; arr[j] = t; } // 原始的shiftDown过程 private static void shiftDown(Comparable[] arr, int n, int k){ while ( 2 *k+ 1 < n ){ int j = 2 *k+ 1 ; if ( j+ 1 < n && arr[j+ 1 ].compareTo(arr[j]) > 0 ) j += 1 ; if ( arr[k].compareTo(arr[j]) >= 0 ) break ; swap( arr, k, j); k = j; } } // 优化的shiftDown过程, 使用赋值的方式取代不断的swap, // 该优化思想和我们之前对插入排序进行优化的思路是一致的 private static void shiftDown2(Comparable[] arr, int n, int k){ Comparable e = arr[k]; while ( 2 *k+ 1 < n ){ //为什么是2*k+1?是不是表示左孩子? int j = 2 *k+ 1 ; if ( j+ 1 < n && arr[j+ 1 ].compareTo(arr[j]) > 0 ) j += 1 ; if ( e.compareTo(arr[j]) >= 0 ) break ; arr[k] = arr[j]; k = j; } //为什么要写这行代码?e是arr[k],没有重新赋值,现在又要赋值给arr[k],看不懂? arr[k] = e; } // 测试 HeapSort public static void main(String[] args) { int N = 1000000 ; Integer[] arr = SortTestHelper.generateRandomArray(N, 0 , 100000 ); SortTestHelper.testSort( "bobo.algo.HeapSort" , arr); return ; } } |
老师你好,麻烦解释下打问号的地方,谢谢!