13.1:堆的heapify下沉过程
13.1:堆的heapify下沉过程
现在的要求是:
此时在大根堆上,将最大的数max返回,剩下的数自动按照大根堆的要求重新建成新的大根堆?
操作思路:
[ 8 7 0 1 6 ]
下标: 0 1 2 3 4
我们知道大根堆上最大值一定在index = 0位置上,所以给用户直接返回max = 8没问题;
返回之前要将这个数8删除??
通过heapSize管着
此时 heapSize = 5,有5个数。
用堆上最后一个数去替换0位置的数,也可以交换。返回max后,heapSize--,一定要减减,heapSize = 4;
[ 6 7 0 1 8 ]
下标: 0 1 2 3 heapSize = 4,4位置的8就被废弃,
由heapSize管着,与左孩子2*i+1进行比较,如果左孩子越界,右孩子肯定越界。
通过heapSize来控制堆的长度
[ 6 7 0 1 8 ]
下标: 0 1 2 3 此时破坏了堆的规则,需要从0位置开始到3位置,将堆调对。
heapify思路:
1、从0位置看它左、右两孩子,找到较大的孩子(如果左、右子树都比0位置数的大,找最大的那个),看是否比0位置的数大;
2、如果较大的数比0位置数大,这个孩子上去,0位置的数下来;
3、下来后,接着按照1和2的思路继续调整;
4、直到这个数没有孩子了 或者 下沉到较大孩子干不过这个数了,调整结束;
1 // 从index位置,往下看,不断的下沉
2 // 停:较大的孩子都不再比index位置的数大;已经没孩子了
3 private void heapify(int[] arr, int index, int heapSize) {
4 int left = index * 2 + 1;
5 while (left < heapSize) { // 如果有左孩子,有没有右孩子,可能有可能没有!
6
7 // 把较大孩子的下标,给largest
8 //右孩子不越界并且右孩子大于左孩子,largest变量指向右孩子的在数组中的位置,否则左孩子的位置
9 int largest = left + 1 < heapSize && arr[left + 1] > arr[left] ? left + 1 : left;
10
11 //拿左、右孩子中更大的那个,和arr[index]位置的数进行比较
12 //largest记录这两个数中更大的那个数的下标位置
13 largest = arr[largest] > arr[index] ? largest : index;
14 if (largest == index) { //是自己那肯定不要交换
15 break;
16 }
17 // index和较大孩子,要互换
18 swap(arr, largest, index); //不是自己那肯定要交换
19 index = largest; //交换后,变更index位置
20 left = index * 2 + 1; //交换后,变更新left位置,继续while循环。
21 }
22 }