pair<int, int> partition3(int arr[], int left, int right){ // 随机选 pivot 并放到最右边 int pivotIndex = left + rand() % (right - left + 1); swap(arr[right], arr[pivotIndex]); int pivot = arr[right];
int lt = left; // < pivot 区间的最后一个位置 int gt = right; // > pivot 区间的第一个位置 int i = left + 1; // 当前扫描元素
voidheapInsert(int[] arr, int index){ while (arr[index] > arr[(index - 1) / 2]){ swap(arr, index, (index - 1) / 2); index = (index - 1) / 2; } }
将数组调整成堆(向下调整)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
voidheapify(int[] arr, int index, int heapSize){ int left = index * 2 + 1; while (left < heapSize){ //比较左子结点和右子节点(判断存在) int largest = left + 1 < heapSize && arr[left +1] > arr[left] ? left + 1 : left; //比较父节点和大子节点 largest = arr[largest] > arr[index] ? largest : index; if (largest == index){ break; } swap(arr, index, largest); index = largest; left = index * 2 + 1; } }
排序
通过index从0到size进行heapInsert来构建大根堆
将根节点与末尾进行交换,并且heapSize–
从根节点开始heapify
循环2、3步
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
voidheapSort(int[] arr){ if (arr == null || arr.length < 2){ return; } for (int i = 0; i < arr.length; i++){ //O(n) heapInsert(arr, i); //O(logn) } //如果给定全部数组而不是一个一个元素,则上面for循环可以优化成O(n),但排序复杂度仍为O(nlogn) //for (int i = arr.length - 1; i >= 0; i--){ // heapify(arr, i, arr.length); //} int heapSise = arr.length; swap(arr, 0, --heapSize); while (heapSize > 0){ //O(n) heapify(arr, 0, heapsize); //O(logn) swap(arr, 0, --heapSize); //O(1) } }