您的位置:首页 > 其它

算法4-9:BST顺序操作

2014-06-10 19:49 134 查看

最大值最小值

最小值就是最左侧的节点,最大值就是最右侧的节点。

代码

public Key min() {
if(root == null) return null;

Node node = root;
while(node.left != null) {
node = node.left;
}
return node.key;
}

public Key max() {
if(root == null) return null;

Node node = root;
while(node.right != null) {
node = node.right;
}
return node.key;
}


floor操作

floor操作就是要在集合中找出不大于指定值的最大值。比如集合为{1,3,5,9},floor(8)是5,因为只有5不超过8,而且于8最接近。

计算floor(x)的时候有三种情况:

要找的节点的值刚好等于x,那么floor(x)就为x

如过x比节点的值小,那么floor(x)的节点一定在左边

如果x比节点的值大,那么floor(x)有可能在右边,也有可能该节点就是floor(x)。只要能在右子树中找到小于等于x的值即可。

因此代码如下:

public Key floor(Key key) {
return floor(root, key);
}

private Key floor(Node node, Key key) {
if(node == null) return null;
int compare = key.compareTo(node.key);

// 如果节点的值和key相等,则该节点就是floor值
if(compare == 0) return node.key;

// 如果key比该节点小,那么floor值一定在节点的左边。
if(compare < 0) return floor(node.left, key);

// 如果key比该节点大,那么floor值一定在节点的右边。
Key k = floor(node.right, key);
if(k != null) return k;
return node.key;
}


size操作

size操作就是用于统计某个树的节点数量,便于实现select操作和rank操作。

要实现size操作,就需要在节点中增加count成员变量,用于统计节点数量。

class Node {
Key key;
Value value;
Node left;
Node right;
int count;
}


size函数的代码如下:

private int size(Node node) {
if(node == null) return 0;
else return node.count;
}


需要修改put操作,记录parent.count。

private Node put(Node parent, Key key, Value value) {
// 如果parent是空的,创建一个新的节点
if(parent == null) {
Node node = new Node();
node.key = key;
node.value = value;
node.count = 1;
return node;
}

// 递归插入
int compare = key.compareTo(parent.key);
if(compare < 0) {
parent.left = put(parent.left, key, value); // 注意:返回值需要赋值给parent.left
} else if(compare > 0) {
parent.right = put(parent.right, key,value);
} else {
parent.value = value;
}
parent.count = 1 + size(parent.left) + size(parent.right);
return parent;
}


rank操作

rank操作就是要找出某个键在集合中的排名。

采用递归的方法就非常方便实现。

public int rank(Key key) {
return rank(root, key);
}

private int rank(Node node, Key key) {
if(node == null) {
return 0;
}

int compare = key.compareTo(node.key);
if(compare < 0) {
return rank(node.left, key);
} else if(compare > 0) {
return size(node.left) + 1 + rank(node.right, key);
} else {
return size(node.left);
}
}


keys操作

keys操作就是按顺序取出所有的键。

对于每个节点,获取左侧节点的所有键,自己的键,获取右侧节点的所有键。也就是中序遍历。

public Iterable<Key> inorder() {
Queue<Key> q = new LinkedList<Key>();
inorder(root, q);
return q;
}

private void inorder(Node node, Queue<Key> q) {
if(node == null) return;
inorder(node.left, q);
q.add(node.key);
inorder(node.right, q);
}


复杂度

对于二叉查找树,所有操作的复杂度都是一样的,复杂度和树的高度成正比。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: