定义
二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树)
它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。 –from 百度百科
增加(put)
原理: 按照大的向右小的向左原则,沿着树的根节点往下找,找到第一个为空的节点或者节点的key和目标key相同时结束,前者插入,后者替换。
/**
* @Description: 插入节点
* @param key
* @param value
* @author wjc920
* @date 2018年6月26日
*/
public void put(K key, V value) {
Node toPut=new Node(key, value);
//在遍历树之前,先判断树是否为空,若空着执行插入,结束
if(root==null) {
root=toPut;
return;
}
Node cur=root;
while(true) {
int cmp=key.compareTo(cur.key);
if (cmp < 0){
//如果代码执行到这里,下一步将对cur的左子树遍历,
//在遍历左子树之前先判断是否为空,若空着执行插入,结束
if(cur.left==null) {
cur.left=toPut;
break;
}
cur=cur.left;
}else if (cmp > 0) {
//如果代码执行到这里,下一步将对cur的右子树遍历,
//在遍历右子树之前先判断是否为空,若空着执行插入,结束
if(cur.right==null) {
cur.right=toPut;
break;
}
cur=cur.right;
}else {
cur.value=toPut.value;
break;
}
}
}
注:非递归
查找
原理: 按照大的向右小的向左原则,沿着树的根节点往下找,找到第一个为空的节点或者节点的key和目标key相同时结束,前者返回空,后者返回值。
/**
* @Description: 获取键key的值
* @param key
* @return
* @author wjc920
* @date 2018年6月26日
*/
public V get(K key) {
return get(root, key).value;
}
private Node get(Node node, K key) {
if (node == null)
return null;
int cmp = key.compareTo(node.key);
if (cmp < 0)
return get(node.left, key);
else if (cmp > 0)
return get(node.right, key);
else
return node;
}
删除
原理: 按照大的向右小的向左原则,沿着树的根节点往下找,找到第一个为空的节点或者节点的key和目标key相同时结束,前者不执行任何操作,后者需要分情况处理:
1. 若待删除的节点只有一个子节点(对应代码中情况2和3),则用子节点替换该节点即可,结束;
2. 若待删除节点没有子节点(对应代码中情况4),直接删除,结束;
3. 若待删除节点有两个子节点(对应代码中情况1),则查找该节点的后继节点,两者交换,然后将后继节点设置为待删除节点,此时回到情况1或2。
/**
* @Description: 删除操作的非递归实现
* @param key
* @return
* @author wjc920
* @date 2018年6月30日
*/
public V remove(K key) {
Node cur=root,target,replace,p=null;
V result;
while(cur!=null) { //寻找target,target.key==key
int cmp=key.compareTo(cur.key); //寻找target,target.key==key
if (cmp < 0){ //寻找target,target.key==key
p=cur; //寻找target,target.key==key
cur=cur.left; //寻找target,target.key==key
}else if (cmp > 0) { //寻找target,target.key==key
p=cur; //寻找target,target.key==key
cur=cur.right; //寻找target,target.key==key
}else //寻找target,target.key==key
break; //寻找target,target.key==key
}
target=cur;
if(target==null) //如果target==null,则不需要删除,返回null
return null; //如果target==null,则不需要删除,返回null
result=target.value; //如果target!=null,则需要删除,先将target的value保存,作为返回结果
if(target.left!=null) {
if(target.right!=null) { //1 如果target.left!=null且target.right!=null
p=target; //找后继节点,即大于target的最小节点
cur=target.right; //找后继节点,即大于target的最小节点
while(cur.left!=null) { //找后继节点,即大于target的最小节点
p=cur; //找后继节点,即大于target的最小节点
cur=cur.left; //找后继节点,即大于target的最小节点
} //找后继节点,即大于target的最小节点
replace=cur; //将后继节点替换tagert
target.key=replace.key; //将后继节点替换tagert
target.value=replace.value; //将后继节点替换tagert
if(replace.right!=null) { //1.1替换后,如果replace.right!=null
replace.key=replace.right.key; //用右节点替换replace,删除右节点
replace.value=replace.right.value; //用右节点替换replace,删除右节点
replace.right=null; //用右节点替换replace,删除右节点
}else { //1.2 替换后,如果replace.right==null
if(p.left==replace) { //删除replace
p.left=null; //删除replace
}else { //删除replace
p.right=null; //删除replace
} //删除replace
}
}else { //2 如果target.left!=null且target.right==null
target.key=target.left.key; //用左节点替换target
target.value=target.left.value; //用左节点替换target
target.right=target.left.right; //用左节点替换target
target.left=target.left.left; //用左节点替换target
}
}else {
if(target.right!=null) { //3 如果target.left==null且target.right!=null
target.key=target.right.key; //用右节点替换target
target.value=target.right.value; //用右节点替换target
target.left=target.right.left; //用右节点替换target
target.right=target.right.right; //用右节点替换target
}else { //4 如果target.left==null且target.right==null
if(p.left==target) { //删除target
p.left=null; //删除target
}else { //删除target
p.right=null; //删除target
}
}
}
return result;
}
本文详细介绍了二叉查找树的基本概念及其核心操作:增加、查找和删除节点的具体实现过程,并提供了非递归实现的示例代码。
860

被折叠的 条评论
为什么被折叠?



