上篇博客我们讨论了一波二叉树,我们知道了二叉树是树的特例同时其实一定程度上,二叉树也可以完全代表树,但是我们又要开始思考。二叉树进行一次search操作我们要进行O(n)个时间复杂度。这样显然我们是不可以接受的,而今天我们讨论的搜索二叉树其实就是在二叉树上进行条件上的约束,通过这个约束我们可以把查找操作缩减到O(lgN),这个是质的提高。 其实熟悉二叉树算法的同志们都知道这个就是二叉树的高度。那么增加啥条件呢,其实我们只要加上左子树比节点val小,右字数比节点val大,就可以实现了。
一言不合先上代码,节点的class和上个博客一样
class BSTNode{
BSTNode left;
BSTNode right;
int val;
BSTNode(int val){
this.val=val;
}
}
下面是搜索操作
public BSTNode search(BSTNode root,int val){
if(root==null){
return null;
}
if(root.val==val){
return root;
}else if(root.val<val){
return search(root.right,val);
}else{
return search(root.left,val);
}
}
根据左边比它小,右边比它大,这样就很容易实现search操作啦。
下面是insert
public void insert(BSTNode root,BSTNode node){
if(node==null) return;
if(root==null) root=node;
if(root.val>node.val){
if(root.left==null) root.left=node;
else insert(root.left,node);
}else{
if(root.right==null) root.right=node;
else insert(root.right,node);
}
}
插入操作和search类似,只是找到一个叶子节点后再进行大小比较,然后进行插入。
BST最复杂的是删除方法
public boolean delete(BSTNode root,int val) {
BSTNode p = root;
BSTNode c = root;
boolean isLeft = false;
while (c.val != val) {
p = c;
if (c.val > val) {
c = c.left;
isLeft = true;
} else {
c = c.right;
isLeft = false;
}
if (c == null) {
return false;
}
}
if (c.left == null && c.right == null) {
if(p==c){
root=null;
return true;
}
if (isLeft)
p.left = null;
else
p.right = null;
} else if (c.left == null) {
if (isLeft)
p.left = c.right;
else
p.right = c.right;
}else if(c.right==null){
if(isLeft)
p.left=c.left;
else
p.right=c.left;
}else{
BSTNode min=findMin(c.right);
c.val=min.val;
delete(c.right,min.val);
}
return true;
}
private BSTNode findMin(BSTNode root){
if(root.left==null)
return root;
return findMin(root.left);
}
删除主要分成两个步奏,第一步找到这个删除的节点以及他的父节点。第二步,判断这个节点,有没有子节点,没有子节点就直接删除,这个时候实现的时候还要注意,删除的BST是只有一个根节点的情况,这种情况直接把root变成null。另一种情况就是只有一个子节点的情况,就把那个子节点取代原来的节点。最复杂的是有两个子节点的情况,这种情况下。我们需要先找到该节点右子树最小的节点。取代该节点,然后把右字数最小那个节点删除。其中的道理是只有用右子树的最小节点或者左子树的最大节点去取代,才不会破坏BST的规则。。。
BST我建议大家看懂代码后自己实现一下难度其实不是很大,下一次我们讨论更加复杂的AVL树。