二叉查找树的创建
1:二叉树的结点类:
代码实现如下:
private class Node{
//存储键
private Key key;
//存储值
public Value vlaue;
//记录左子结点
public Node left;
//记录右子结点
public Node right;
//构造函数
public Node(Key key,Value value,Node left,Node right){
this.key = key;
this.vlaue = value;
this.left = left;
this.right = right;
}
}
2:二叉查找树API设计:
public void put(Key key,Value value):向树中添加元素key–value
private Node put(Node x,Key key,Value value):向指定的树x中添加key-vlaue,并返回添加元素后新的树
----------------插入方法put实现思想:
1.如果当前树中没有任何一个结点,则直接把新结点当做根结点使用;
2:如果当前树不为空,则从根结点开始:
··········2.1:如果新结点的key小于当前结点的key,则继续查找当前结点的左子结点;
··········2.2:如果新结点的key大于当前结点的key,则继续查找当前结点的右子结点;
··········2.3:如果新结点的key等于当前结点的key,则树中已经存在这样的结点,替换该结点的value值即可;
代码实现入下:
//向树中添加元素key--value
public void put(Key key,Value value){
root = put(root,key,value);
}
//向指定的树x中添加key-vlaue,并返回添加元素后新的树
private Node put(Node x,Key key,Value value){
//如果x子树为空
if(x == null){
N++;
return new Node(key,value,null,null);
}
//如果x子树不为空
//比较x结点的键和key的大小
int cmp = key.compareTo(x.key);
if(cmp > 0){
//如果key大于x结点的键,则继续找x结点的右子树
x.right = put(x.right,key,value);
}else if(cmp < 0){
//如果key小于x结点的键,则继续找x结点的左子树
x.left = put(x.left,key,value);
}else {
//如果key等于x结点的键,则替换x结点的值为value
x.vlaue = value;
}
return x;
}
public Value get(Key key):查询树中指定key对应的value
public Value get(Node x,Key key):从指定的树x中,查找key对应的值
----------------查找方法get实现思想:
从根节点开始:
·········1:如果要查询的key小于当前结点的key,则继续查找当前结点的左子结点;
·········2:如果要查询的key大于当前结点的key,则继续查找当前结点的右子结点;
·········3:如果要查询的Key等于当前结点的key,则树中返回当前结点的value;
代码实现入下:
//查询树中指定key对应的value
public Value get(Key key){
return get(root,key);
}
//从指定的树x中,查找key对应的值
public Value get(Node x,Key key){
//x树为Null
if(x == null){
return null;
}
//x树不为null
//比较key和x结点的键的大小
int cmp = key.compareTo(x.key);
if(cmp > 0){
//如果key大于x结点的键,则继续找x结点的右子树
return get(x.right,key);
}else if(cmp < 0){
//如果key小于x结点的键,则继续找x结点的左子树
return get(x.left,key);
}else {
//如果key等于x结点的键,则替换x结点的值为value
return x.vlaue;
}
}
public void delete(Key key):删除树中key对应的value
public Node delete(Node x,Key key):删除指定树x中的key对应的value,并返回删除后的新树
----------------删除方法delete实现思想:
1:找到被删除的结点;
2:找到被删除结点右子树中的最小结点minNode;
3:删除右子树中的最小结点;
4:让被删除结点的左子树称为最小结点minNode的左子树,让被删除结点的右子树成为最小结点minNode的右子树;
5:让被删除结点的父节点指向最小结点minNode;
代码实现入下:
//删除树中key对应的value
public void delete(Key key){
delete(root,key);
}
//删除指定树x中的key对应的value,并返回删除后的新树
public Node delete(Node x,Key key){
//x树为null
if(x == null){
return null;
}
//x树不为null
int cmp = key.compareTo(x.key);
if(cmp > 0){
//如果key大于x结点的键,则继续找x结点的右子树
x.right = delete(x.right,key);
}else if(cmp < 0){
//如果key小于x结点的键,则继续找x结点的左子树
x.left = delete(x.left,key);
}else {
//如果key等于x结点的键,完成真正的删除结点动作,要删除的结点就是x
//让元素个数-1
N--;
//得找到右子树中最小得结点
if(x.right == null){
return x.left;
}
if(x.left == null){
return x.right;
}
Node minNode = x.right;
while (minNode.left != null){
minNode = minNode.left;
}
//删除右子树中最小得结点
Node n = x.right;
while (n.left != null){
if(n.left.left == null){
n.left = null;
}else {
//变换n结点即可
n = n.left;
}
}
//让x结点得左子树成为minNode的左子树
minNode.left = x.left;
//让x结点的右子树成为minNode的右子树
minNode.right = x.right;
//让x结点的父结点指向minNode
x = minNode;
}
return x;
}
下面为完整代码(附带检测):
public class BinaryTree<Key extends Comparable<Key>,Value> {
//记录根节点
private Node root;
//记录树中元素的个数
private int N;
private class Node{
//存储键
private Key key;
//存储值
public Value vlaue;
//记录左子结点
public Node left;
//记录右子结点
public Node right;
//构造函数
public Node(Key key,Value value,Node left,Node right){
this.key = key;
this.vlaue = value;
this.left = left;
this.right = right;
}
}
//获取树中元素的个数
public int size(){
return N;
}
//向树中添加元素key--value
public void put(Key key,Value value){
root = put(root,key,value);
}
//向指定的树x中添加key-vlaue,并返回添加元素后新的树
private Node put(Node x,Key key,Value value){
//如果x子树为空
if(x == null){
N++;
return new Node(key,value,null,null);
}
//如果x子树不为空
//比较x结点的键和key的大小
int cmp = key.compareTo(x.key);
if(cmp > 0){
//如果key大于x结点的键,则继续找x结点的右子树
x.right = put(x.right,key,value);
}else if(cmp < 0){
//如果key小于x结点的键,则继续找x结点的左子树
x.left = put(x.left,key,value);
}else {
//如果key等于x结点的键,则替换x结点的值为value
x.vlaue = value;
}
return x;
}
//查询树中指定key对应的value
public Value get(Key key){
return get(root,key);
}
//从指定的树x中,查找key对应的值
public Value get(Node x,Key key){
//x树为Null
if(x == null){
return null;
}
//x树不为null
//比较key和x结点的键的大小
int cmp = key.compareTo(x.key);
if(cmp > 0){
//如果key大于x结点的键,则继续找x结点的右子树
return get(x.right,key);
}else if(cmp < 0){
//如果key小于x结点的键,则继续找x结点的左子树
return get(x.left,key);
}else {
//如果key等于x结点的键,则替换x结点的值为value
return x.vlaue;
}
}
//删除树中key对应的value
public void delete(Key key){
delete(root,key);
}
//删除指定树x中的key对应的value,并返回删除后的新树
public Node delete(Node x,Key key){
//x树为null
if(x == null){
return null;
}
//x树不为null
int cmp = key.compareTo(x.key);
if(cmp > 0){
//如果key大于x结点的键,则继续找x结点的右子树
x.right = delete(x.right,key);
}else if(cmp < 0){
//如果key小于x结点的键,则继续找x结点的左子树
x.left = delete(x.left,key);
}else {
//如果key等于x结点的键,完成真正的删除结点动作,要删除的结点就是x
//让元素个数-1
N--;
//得找到右子树中最小得结点
if(x.right == null){
return x.left;
}
if(x.left == null){
return x.right;
}
Node minNode = x.right;
while (minNode.left != null){
minNode = minNode.left;
}
//删除右子树中最小得结点
Node n = x.right;
while (n.left != null){
if(n.left.left == null){
n.left = null;
}else {
//变换n结点即可
n = n.left;
}
}
//让x结点得左子树成为minNode的左子树
minNode.left = x.left;
//让x结点的右子树成为minNode的右子树
minNode.right = x.right;
//让x结点的父结点指向minNode
x = minNode;
}
return x;
}
}
//主程序
public class TestBinaryTree {
public static void main(String[] args) {
//创建二叉查找树对象
BinaryTree<Integer, String> tree = new BinaryTree<>();
//测试插入
tree.put(3,"张三");
tree.put(2,"李四");
tree.put(1,"王五");
tree.put(4,"赵六");
tree.put(5,"杨七");
System.out.println("插入完毕后元素的个数:"+tree.size());
//测试获取
System.out.println("键5对应的元素是:"+tree.get(5));//杨七
//测试删除
tree.delete(2);
System.out.println("删除后的元素个数:"+tree.size());
System.out.println("删除后键2对应的元素;"+tree.get(2));
}
}