我目前正在实施一种算法,在这种算法中我需要知道已经读过的数字的数量小于当前正在处理的数字。
这样做的方法是通过合并排序,但我对BST方法更感兴趣。
此过程旨在以O(log n)
计算值小于关键节点值的节点数:
countLessThan(int x, node T)
if T = null
return
if T.value >= x
countLessThan(x, T.left) // T.left contains only numbers < T.value and T.right only numbers > T.value
else
globalResult += T.numLeft
countLessThan(x, T.right)
在这种情况下,numLeft
字段将存储在每个节点中,并表示其左子树中的节点数(包括其自身)。
所以我的问题是,如何快速更新这个特定领域?
答案 0 :(得分:2)
您可以在每个节点中存储连接到左侧(小于)侧的叶子数,并在插入新叶时为左侧传递的每个分支增加此计数。
通过在插入时添加右侧传递的分支的所有计数,可以同时计算小于新插入值的值的数量。
以下是用于演示该方法的JavaScript代码段:
function CountTree() { // tree constructor
this.root = null;
this.insert = function(value) {
var branch = null, node = this.root, count = 0, after;
while (node != null) { // traverse tree to find position
branch = node;
after = value > node.value; // compare to get direction
if (after) {
node = branch.right; // pass on the right (greater)
count += branch.count; // add all nodes to the left of branch
} else {
node = branch.left; // pass on the left (smaller or equal)
++branch.count; // increment branch's count
}
} // attach new leaf
if (branch == null) this.root = new Leaf(value);
else if (after) branch.right = new Leaf(value);
else branch.left = new Leaf(value);
return count;
}
function Leaf(value) { // leaf constructor
this.value = value;
this.left = null;
this.right = null;
this.count = 1;
}
}
var t = new CountTree(), v = [5, 3, 8, 2, 4, 7, 9, 1, 4, 7, 8];
for (var i in v) {
document.write("Inserting " + v[i] + " (found " + t.insert(v[i]) + " smaller)<BR>");
}
&#13;
这是代码中示例中的树,插入最后一个元素时(第二个值为8)。每个节点都在其右侧顶点下方打印了左侧(包括其自身)的节点数。插入第二个8时,传递值为5,8和7的节点;其中,5和7在右边传递,它们的计数之和为6 + 2 = 8,因此在树中有8个小于8的值:1,2,3,4,4,5,7 7.值为8的第一个节点在左侧传递,因此其计数将从3增加到4.