在使用堆实现的二叉搜索树中,对于节点 P 找到其键立即小于 P 的键的节点

In a binary search tree implemented using a heap, for a node P find the node with the key that is immediately smaller than the key of P

在使用堆实现的二叉搜索树中(因此二叉树用向量表示),对于节点P,找到其键立即小于P的键的节点。

例如,这里的 p 键为 13,下一个较小的键是 11

我认为一旦你找到 p 你应该向左走一次,然后尽可能向右走

In a binary search tree implemented using a heap

堆具有不同的属性:

  • 堆是一个完全二叉树。 BST 不必是完整的(如示例中所示)。数组表示取决于此属性。没有它,数组表示是不明确的:“差距”将如何表示?
  • 堆节点的children的值不小于节点的值(当它是min-heap时),而BST节点的左child(如果有的话)的值不大于节点的值

最后看这题数据结构只是一个细节

I think once you find p you should go once to the left, then go as much to the right as you can

这是一种情况。当p一个leftchild时确实是正确的。如果不是,你应该向上移动,直到你从child向上移动。那么你就到了前面的节点了

代码

我假设表示为数组将具有以下特征:

  • 数组会根据需要动态增长
  • 未使用的数组条目将获得保留值 (undefined)

这是 JavaScript 中的一个实现:

class BST extends Array {
    add(value) {
        let i = 0;
        while (i < this.length && this[i] !== undefined) {
            let nodeValue = this[i];
            i = i * 2 + 1;
            if (value >= nodeValue) {
                i++;
            }
        }
        // Extend array ... although JS would do this automatically..
        while (this.length <= i) {
            this.push(undefined);
        }
        this[i] = value;
        return this;
    }
    predecessor(i) {
        // if has left child...
        let child = i * 2 + 1;
        if (child < this.length && this[child] !== undefined) {
            // then find right most descendent
            while (child < this.length && this[child] !== undefined) {
                i = child;
                child = child * 2 + 2;
            }
            return i;
        }
        // otherwise, while it is a left child, go up
        while (i % 2 == 1) {
            i = (i - 1) / 2; 
        }
        if (i > 0) { // not the root, but a right child of a parent
            return (i - 2) / 2;
        }
        // We reached the root... there is no predecessor
        return -1;
    }
}

// Demo
let bst = new BST();
// Load example tree
bst.add(16).add(7).add(6).add(13).add(10).add(8).add(11);
// Find node with value 16
let i = bst.indexOf(16);
// Keep walking to the node that precedes it...
while (i >= 0) {
    console.log(`bst[${i}] == ${bst[i]}`);
    i = bst.predecessor(i);
}

注意数组的使用索引是如何分散的:很多条目实际上是“间隙”,即未使用的条目。