一、二叉树定义:
二叉树就是度不超过2的树(即每个节点最多有两个子结点)
满二叉树定义:
一个二叉树,每一层的结点树都达到了最大值,就称为满二叉树
二、二叉查找树API设计:
- 二叉查找树每个结点都是储存一个key和一个value。
- 本文用链表实现二叉查找树
三、二叉查找树的实现
接口Comparable<T>的使用:
- 注意程序这里要写上Key继承了Comparable接口,然后后面才可以调用compareTo方法
四、二叉查找树的增(put)删(delete)查(get)
package day02;
public class BinaryTree<Key extends Comparable<Key>,Value>{
private Node root;//根结点
private int N;//结点个数
//内部类
class Node{
public Node left; //左子结点
public Node right; //右子结点
public Key key;
public Value value;
//构造器
public Node(Node left,Node right,Key key,Value value){
this.left = left;
this.right = right;
this.key = key;
this.value = value;
}
}
public int size(){
return N;
}
//向整个树中添加结点 key-value
// 注意:此方法会把新插入的值作为root结点
public void put(Key key, Value value){
root = put(root,key,value);
}
//在指定结点x下的子树中插入新的结点 key-value
public Node put(Node x, Key key, Value value){
//如果x结点为空
if(x==null){
N++;
return new Node(null,null,key,value);
}
//如果x结点不为空,则比较x.key和key的大小
int var = key.compareTo(x.key);
if(var>0){
//即key大于x结点的键
x.right = put(x.right,key,value);//用了递归的思想
}else if(var<0){
x.left = put(x.left,key,value);
}else{
x.value = value;
x.key = key;
}
return x;//x即为新被插入的结点
}
//在整个树中查询指定key对应的value
public Value get(Key key){
return get(root,key);
}
//在指定结点下查找指定key对应的value
public Value get(Node x,Key key){
//1.当x=null
if(x==null){
return null;
}
//2.当x!=null
int var = key.compareTo(x.key);
if(var>0){
return get(x.right,key);//用了递归的思想
}else if(var<0){
return get(x.left,key);
}else{
//找到了目标结点
return x.value;
}
}
//删除树中对应的key结点
public void delete(Key key){
delete(root,key);
}
//删除指定结点x下的对应key结点,并返回
public Node delete(Node x,Key key){
//1.x为null
if(x==null){
//说明没找到对应结点
return null;
}
//2.x不为null
int var = key.compareTo(x.key);
if(var>0){
x.right = delete(x.right,key);
}else if(var<0){
x.left = delete(x.left,key);
}else{
//找到了待删除结点x
N--;
//1.只有左子树
if(x.right==null){
return x.left;
}
//2.只有右子树
if(x.left==null){
return x.right;
}
//3.x左右子树都有,找到x右子树中的key最小值结点minNode来替换待删除结点,然后删除原来位置的minNode连接
Node minNode = x.right;
while(minNode.left!=null){
minNode = minNode.left;
}//此时minNode为x右子树中的key最小值结点
//断开minNode的连接
Node n = x.right;
while(n.left!=null){
if(n.left.left==null){
n.left = null;
}else{
n = n.left;
}
}
minNode.left = x.left;//让minNode的左子树指向x的左子树
minNode.right = x.right;//让minNode的右子树指向x的右子树
//让x结点的父结点指向minNode
x = minNode;//因为程序前面有x.right = delete(x.right,key);,递归时就让x结点的父结点指向minNode
}
return x;
}
//查找整个树的最小键
public Key minKey(){
return minKey(root).key;
}
//指定树x中找出最小键所在结点
//注意x结点右侧子树的所有结点都比x的key大
public Node minKey(Node x){
//此方法采用循环,没有有迭代。效果一样
while (x.left!=null){
x = x.left;
}
return x;
}
//查找整个树中最大的键
public Key maxKey(){
return maxKey(root).key;
}
//查找指定树x中最大键所在结点
//递归的条件:1.可以分解成很多子问题2.每一次递归调用,子问题使情况朝着基准情况推进3.基准情况即不用递归便可解出
public Node maxKey(Node x){
if(x.right!=null){
return maxKey(x.right);
}else {
return x;
}
}
}
测试程序:
五、二叉查找树的遍历