关于这一部分的知识没有想的太明白,因此肯定表达不是很清楚,因此直接上代码了,后续再进行消化。
package mypackage;
import com.sun.security.auth.module.UnixLoginModule;
import javax.print.DocFlavor;
import java.util.IllegalFormatCodePointException;
//二叉树类
class Btree<key extends Comparable, value> {
public Node root;
public int N;
// 节点类,包括键值对,左子节点和右子节点
public class Node {
public key key;
public value value;
public Node left;
public Node right;
public Node(key key, value value, Node left, Node right) {
this.key = key;
this.value = value;
this.left = left;
this.right = right;
}
}
// 获取元素个数
public int size() {
return N;
}
// 向树中添加元素,这个是对外调用的方法,从root开始递归,添加元素
// 核心是下面的put(Node node, key key, value value)方法
public void put(key key, value value) {
root = put(root, key, value);
}
// 向指定树中添加元素
public Node put(Node node, key key, value value) {
// 如果子树node为空,直接返回新节点
// 其实这个是递归结束的条件之一
if (node == null) {
N++;
return new Node(key, value, null, null);
}
// 判断如果key大于node.key,向右子树递归
int compare1 = key.compareTo(node.key);
if (compare1 > 0) {
// 注意为什么不put(node.right, key, value),还要加上node.right = ?
// 这样才能实现节点节点之间的连接,因为put(node.right, key, value);返回的是node.right
node.right = put(node.right, key, value);
// 判断如果key小于node.key,向左子树递归
} else if (compare1 < 0) {
node.left = put(node.left, key, value);
// 判断如果key==node.key,替换这个值
} else {
node.value = value;
}
// 返回这个节点
return node;
}
// 查询某key的值这个是对外调用的方法,从root开始递归,查询元素
// 核心是下面的get(Node node, key key)方法
public value get(key key){
return get(root,key);
}
// 查询指定子树某key的值
public value get(Node node, key key){
// 如果为空,无法找到,返回null
if (node==null){
return null;
}
int compare1 = key.compareTo(node.key);
// 判断如果key大于node.key,向右子树递归
if (compare1 > 0) {
return get(node.right,key);
// 判断如果key小于node.key,向左子树递归
} else if (compare1 < 0) {
return get(node.left,key);
// 判断如果key==node.key,找到这个值
} else {
return node.value;
}
}
// 删除操作,比较麻烦的操作,
// 主要是因为删除一个节点后,原本这个节点有左右子树的话,要找一个节点去填充这个节点,
// 找哪个节点去填充呢,找右子数种最小的节点,这个节点能满足大于左子树种中的所有节点,小于右子树的所有节点
// 如果这个节点没有右子树,只有左子树,让上一个节点连接这个节点的下一个节点
// 如果没有左、右子树,直接删除就行了
public void delete(key key){
root=delete(root,key);
}
// 删除指定数种的key对应的value,并返回删除后的新树
public Node delete(Node node,key key){
// 如果节点不存在就返回null
if (node==null){
return null;
}
int compare1 = key.compareTo(node.key);
// 判断如果key大于node.key,向右子树递归
if (compare1 > 0) {
// 递归,结果返回删除后的新树,让node.right指向返回的新树
node.right = delete(node.right, key);
// 判断如果key小于node.key,向左子树递归
} else if (compare1 < 0) {
// 递归,结果返回删除后的新树,让node.left指向返回的新树
node.left = delete(node.left, key);
// 判断如果key==node.key,找到了这个要删除的值,之后要找到一个值来填充这个位置
} else {
N--;
// 如果没有右子树,返回的新树为当前结点的左子树即可
if (node.right==null){
return node.left;
}
// 如果没有左子树,返回的新树为当前结点的右子树即可
if (node.left==null){
return node.right;
}
// 如果有左子树和右子树,去找右子树中的最小的值
Node minNode=node.right;
// 一直找左子树就是最小的值,如果没有左子树,那么当前就是最小的值
while (minNode.left!=null){
minNode=minNode.left;
}
// 上面找到了最小节点,现在要删除这个最小节点,然后放到待删除的节点处覆盖
// 怎么删除呢,就是要找到这个节点的上一个节点,让他指向null
// 因此关键就是要找到最小节点的上一个节点
Node cur=node.right;
Node pre=node;
// 如果待删除节点的右子树有左节点,那么就去找这个最小的左节点
// 然后让最小节点的上一个节点指向null
if (cur.left!=null){
while (cur.left!=null){
pre=cur;
cur=cur.left;
}
pre.left=null;
// 如果待删除节点的右子树没有左节点,这个时候又要分两种情况
// 一种情况是没有左节点且没有右节点,这时让node.right指向null即可
// 另外一种情况是没有左节点但是有右节点,因此要让node.right指向node.right.right
}else {
if (cur.right==null){
pre.right=null;
}else {
pre.right=cur.right;
}
}
// 删除最小元素后,让最小元素左子树为待删除元素的左子树,让最小元素右子树为待删除元素的右子树
minNode.left=node.left;
minNode.right=node.right;
// 这个是让node的上一个节点指向这个最小的节点,此时这个最小的节点已经替换了待删除的元素的位置
node= minNode;
}
// 这个返回值至关重要,作为这个方法的返回值,
// 用作上一级的node.right = delete(node.right, key)或者node.left = delete(node.left, key)的返回值
return node;
}
// 查找树中最小的key,调用重载方法
public key getmin(){
return getmin(root).key;
}
// 查找指定树中最小的key的节点
// 递归去找右子树
public Node getmin(Node node){
if (node.left!=null){
return getmin(node.left);
}else {
return node;
}
}
// 查找树中最大的key,调用重载方法
public key getmax(){
return getmax(root).key;
}
// 查找指定树中最大的key的节点
// 递归去找右子树
public Node getmax(Node node){
if (node.right!=null){
return getmax(node.right);
}else {
return node;
}
}
}
//测试
public class MyJava {
public static void main(String[] args) {
Btree<Integer,String>btree=new Btree();
// 插入元素
btree.put(6,"刘备");
btree.put(4,"关羽");
btree.put(9,"张飞");
btree.put(1,"曹操");
btree.put(5,"吕布");
btree.put(7,"黄忠");
btree.put(10,"赵云");
System.out.println("插入完毕后元素的个数为:"+btree.size());
// 查询元素
System.out.println("查询key=4元素:"+btree.get(4));
// 找最小的key
System.out.println("最小的key:"+btree.getmin());
// 找最大的key
System.out.println("最大的key:"+btree.getmax());
// 删除元素
btree.delete(4);
System.out.println("删除后元素个数:"+btree.size());
System.out.println("删除后查询4元素:"+btree.get(4));
}
}
结果: