关于小根堆的结点删除问题

众所周知,小根堆是任意非叶结点的值都不大于其左子树和右子树的都任一结点的值

img


小根堆结点的删除就是,用最后一个元素代替被删除的结点,如果该结点的值不是其左子树和右子树中值最小的结点,就将该结点“下坠”。
加入我们要删除"101"这个结点,那么就该用"9"来代替。

img

显示,"9"不需要下坠,但是"9"与其兄弟结点以及父结点显然不满足小根堆的定义。

img

按理说,这个时候应该将"9"上移,但是我在学习小根堆结点删除的时候,并没有提到这种操作,这个时候我该怎么办?

此时,是小根堆的下面的节点所成的小根堆成问题。首先,从头部向下进行小根堆的建立是不行的,与混乱的堆插入一个值,想让其变为小根堆一样“荒谬”。所以,我们需要从下面的堆进行。与push行为有类似的操作(可以互通理解):只有先前是小根堆后,后面的调整才成立。此处的“插入”,只不过是从下到上的堆的根节点。所以,需要找到最后的一个堆的根,即:(n - 1 - 1) / 2,然后往上:

for (int i = (n - 1 - 1) / 2; i >= 0; --i)
    Adjust_down(i); //就是普通的向下调整

img

直接拿要删除的节点的叶子节点代替,就只有下坠操作了,要删除节点的叶子节点肯定大于要删除的节点