二叉查找树
能够将链表插入的灵活性和有序数组查找的高效性结合起来的符号实现
在二叉树中,每个节点只能有一个父节点(只有一个例外,也就是根节点,它没有父节点),每个节点到只有左右两个链接分别指向自己的左子节点和右子节点 节点都看成一棵相对于父节点较小的二叉树 即 子二叉树
在二叉查找树中的每一个节点还包含键和值
有了定义 那么该怎么是实现 从节点定义开始 节点的定义类似于java集合源码中的TreeNode 这里略去
数据表示
在java集合中嵌套定义了一个私有类来表示二叉树上的一个节点 每个节点都含有一个键 一个值 一条左链接 和一条右链接
`` 左链接指向一颗小于该节点的所有键组成的二叉平衡树 右链接指向一颗大于该节点的所有键组成的二叉平衡树;
二叉树的get思路
- 如果待查找的节点 比根节点小 则选择左子树继续查找
- 如果待查找的节点 比根节点大 则选择右子树继续查找
- 当找到一个含有被查找的键的节点或者当前子树变为空时这个过程才会结束
private Value get(Node x,Key key){
if(x==null) return null;
int cmp=key.compareTo(x.key);
if(cmp<0) return get(x.left,key);
else if(cmp>0) return get(x.right,key);
else return x.val;
}
二叉树的put
- 找到插入位置 即查找到一个不存在于树中的节点并结束于一条空链接时
- 将链接指向一个含有被查找的键的新节点
- 跟新每个子二叉树 因为 放入了新的节点
public void put(Key key,Value val){
root=put(root,key,value);
}
private Node put(Node x,Key key,Value val){
if(x==null) return new Node(key,val,1);
int cmp=key.compareTo(x.key);
if(cmp<0) x.left=put(x.left,key,val);
else if(cmp>0) x.right=put(x.right,key,val);
else x.val=val;
x.N=size(x.left)+size(x.right)+1;
//为什么要返回x 因为插入新节点后 每个子二叉树都要更新 return x;
}
二叉查找树分析
- 在最好的情况下,一颗含有N个节点的树是完全平衡的
最大键和最小键
- 如果根节点的左链接为空,那么最小键就是根节点
- 否则递归的查找左链接的左链接
public Key min(){
return min(root).key;
}
private Node min(Node x){
if(x.left==null) return x;
return min(x.left);
}
private Node myMin(Node x){
}
向下取整和向上取整
public Key floor(Key k){v
return floor(root,k);
}
/**
整个函数的意思就是先找到该节点的位置 返回最近一次调用右链接所代表的那个节点
*/
private Key floor(Node x,Key k){
//返回最近一次的右链接
//这样的确可以找到Key的节点 始终是最小的
if(x==null ) return x;
int cmp=key.compareTo(x.key);
if(cmp==0)
return x;
if(cmp<0)
return floor(x.left,key);
//这里省略了else
Node t=floor(x.right,key);
if(t!=null)
return t;
else
return x;
}