定义
二叉查找树是一颗二叉树。
每个节点的键值都大于左子树任意节点的键值而小于右子树任意节点的键值。
TIPs:树的算法可以很容易用递归。因为树的子节点也可以看做一颗树。
基本实现
数据表示
求节点的size(伪代码):
public int size(tree):
if tree==null:
return 0;
else:
return size(tree.left)+size(tree.right)+1;
查找
伪代码:
public key get(target,tree):
if tree==null:
return null;
if tree.key==target:
return tree;
else if tree.key >target:
return get(target,tree.left);
else:
return get(target,tree.left);
TIPs:一般基本类型都可以用compareTo()比较,如字符串,不能直接使用“==”比较。
Exmaple: int cmp=target.compareTo(tree.key);(cmp>0时,target>tree.key)
插入
和查找类似,找到最后的空节点,把键值插入。
分析
和快速排序比较:很相似,根结点就是快排的第一个切分元素
和二分排序比较:查找速度比二分排序慢39%,但是插入速度二叉查找树是对数级别,二分数组需要线性级别。
有序性相关的方法
最大键和最小键
最大键就是一直找右子树,最小键找左子树
向上取整和向下取整
如果给定的key小于二叉查找树的根结点的键,那么小于等于key的最大键floor(key)一定在根结点的左子树中,如果给定的键key大于二叉树的根结点,那么只有当根节点右子树种存在小于等于key的结点时,小于等于key的最大键才会出现在右子树种,否则根节点就是小于等于key的最大键
选择操作select()
找到排名为k的键(即树中正好有k个小于它的键)
如果左子树种的节点数t>k,则继续在左子树中找排名为k 的键
如果t==k,则直接返回根节点的键,
如果t小于k, 则在右子树中找排名为k-t-1的键;
排名操作rank()
rank()是select()的逆方法。
如果给定的键和根节点的键相等,返回左子树的节点总数t
如果给定的键小于根节点,则返回左子树中的排名
如果给定的键大于根节点,则返回t+1+右子树排名
删除最大键和最小键
deleteMin():不断深入根节点的子节点,然后遇到一个空链接,然后将指向该节点的链接指向该节点的右子树
删除操作(hard)
如果要删除的结点只有一个子结点,跟上面的类似
如果要删除的节点有两个子结点。
删除节点以后,用它的后继结点替代它。
后继节点:右子树中的最小结点
步骤:
- 将指向要删除的节点x的链接保存为t
- 将x指向它的后继结点min(t.right)
- 将x的右链接指向deleteMin(t.right),也就是在删除后所有结点仍然大于x.key的子二叉查找树
- 将x的左链接设为t.left
范围查找
建立一个队列
if(cmplo<0) keys(x.left,queue,lo,hi);
if(cmplo<=0&&cmphi>=0) queue.enqueue(x.key);
if(cmphi>0) keys(x.right,queue,lo,hi);
递归地查找根节点的左子树,然后查找根节点,然后查找根节点的右子树。