二分搜索树主要用于表查询(字典查询)
查找 | 插入 | 删除 | |
---|---|---|---|
普通数组 | O(N) | O(N) | O(N) |
顺序数组 | O(logN) | O(N) | O(N) |
二分搜索树 | O(logN) | O(logN) | O(logN) |
可以高效的动态维护数据。
二分搜索树删除任意节点:
如果删除节点的左右子树都不为空,则可以找到该节点右子树的最小值代替该节点,然后删除该节点右子树的最小节点。
//删除树中任意节点
public void remove(int key){
remove(root,key);
}
public Node remove(Node node,int key){
if(node==null)
return null;
if(node.key>key){
node.left = remove(node.left,key);
return node;
}
else if(node.key<key){
node.right = remove(node.right,key);
return node;
}
else{
if(node.left==null){
Node right = node.right;
count--;
return right;
}
if(node.right==null){
Node left = node.left;
count--;
return left;
}
Node rightMin = minimum(node.right);
Node successor = new Node(rightMin);
successor.right = removeMin(node.right);
successor.left = node.left;
return successor;
}
}
//找到以node为根节点的最小节点
private Node minimum(Node node){
if(node.left==null)
return node;
return minimum(node.left);
}
//删除以node为根节点最小节点
private Node removeMin(Node node){
if(node.left==null){
Node right = node.right;
count--;
return right;
}
node.left = removeMin(node.left);
return node;
}
二分搜索树删除节点非常高效,时间复杂度是O(logN)。
二分搜索树还支持rank(看某一个元素排第几名)和select(看第几名的元素是什么)操作。可以在每个节点的构造函数中存储一个count元素,代表以这个节点为根有多少个节点。
另外二分搜索树可以支持重复元素,简单的想法是节点左子树存储小于等于该节点的值的节点,右子树存储大于该节点的值的节点。但这种数据结构比较浪费空间,可以在每个节点的构造函数中添加一个count元素,代表与根节点的数值相等的节点的个数。