为什么要引入索引堆
在堆排序中,比如最小堆,我们从最后一个非叶子结点开始(上图示例中索引 8/2 = 4)一直到索引1,经过不断的调整(shiftDown),使得最小值调整到堆顶。在这个调整的过程中,进行了元素的交换。若这个元素是较为复杂的结构的话,会产生较大性能的消耗;还有一个问题就是,成最小堆之后,原来的data[1] = 92 将变成最小值 30,若我们想改变原来data[1] = 92 的值,就很难找到92在成堆之后的位置,元素位置发生改变,只能重新遍历数组。由此引出索引堆来解决这个问题。
void shifDown(int k) {
while (2 * k <= count) {
int j = 2 * k;
if (j + 1 <= count && data[j + 1] <= data[j])
j++;
if (data[k] <= data[j])
break;
swap(data[k], data[j]);
k = j;
}
}
索引堆的算法描述
以最小索引堆为例,以元素的索引去构建堆。初始状态下:节点里面是索引号
- 从最后一个非叶子结点的索引 i 开始;
- 若索引 i 所在树的左右孩子的元素都比他大,不要做交换;
- 若索引 i 所在树的左右孩子中有比它更小的,则将元素所在的索引进行交换;