类名 | BinaryTree |
---|---|
构造方法名 | public BinaryTree() |
成员内部类 | public class Node;结点类 |
成员方法 | public void put(Key key, Value value);往树中插入一个键值对 public Node put(Node x, Key key, Value value);在指定树x上,添加一个键值对,并返回添加后的新树 public Value get(Key key);根据key 返回value; public int length();获取线性表数据个数(长度) public T remove(int index);删除指定索引处元素,并将其返回 public Value get(Node x, Key key) ;从指定树中找出对应的值 public void delete(Key key);根据key,删除树中对应的键值对 public Node delete(Node x, Key key);删除指定树x上的键为key 的键值对,并返回删除后的新树 public int size();获取树中元素的个数 public Key min() ;查找整个树中最小的键 public Node min(Node x);在指定树x 中找出最小键所在的结点 public Key max();查找整个树中最大的键 public Node max(Node x);在指定树x 中找出最大键所在的结点 public Queue preErgodic();前序遍历获取整个树中所有的键 public void preErgodic(Node x, Queue keys);前序遍历获取指定树x 的所有键,并放到keys 队列中 public Queue midErgodic();使用中序遍历获取所有的键 private void midErgodic(Node x, Queue keys);使用中序遍历获取指定x中所有的键,并存放到key中 public Queue afterErgodic();使用后序遍历,把整个树中所有的键返回 private void afterErgodic(Node x, Queue keys);使用后序遍历,把指定x树中所有的键放入到keys 中 |
成员变量 | private int size;记录当前线性表的元素个数 private Node head;;定义头结点 |
成员内部类变量 | private Node left;记录左子结点 private Node right;记录右子结点 private Key key;记录key private Value value;记录value |
代码如下
输出结果
key 为E 的值是:5
key 为B 的值是:2
树中元素个数是:8
树中最小值是:1
树中最大值是:8
E-----2
B-----2
A-----1
D-----4
C-----3
G-----7
F-----6
H-----8
测试类
public static void main(String[] args) {
BinaryTree<String, String> tree = new BinaryTree<>();
tree.put("E", "5");
tree.put("B", "2");
tree.put("G", "7");
tree.put("A", "1");
tree.put("D", "4");
tree.put("F", "6");
tree.put("H", "8");
tree.put("C", "3");
System.out.println("key 为E 的值是:"+tree.get("E"));
System.out.println("key 为B 的值是:"+tree.get("B"));
System.out.println("树中元素个数是:"+tree.size());
System.out.println("树中最小值是:"+ tree.min());
System.out.println("树中最大值是:"+ tree.max());
//前序遍历
Queue<String> keys = tree.preErgodic();
for (String key : keys){
System.out.println(key+"-----"+tree.get(key));
}
}
BinaryTree类
package cn.bloghut.tree;
/**
* @author by 闲言
* @classname BinaryTree
* @description 自定义二叉树api
* @date 2021/7/21 10:53
*/
public class BinaryTree<Key extends Comparable, Value> {
//存储元素个数
private int size;
//头结点
private Node head;
public class Node {
//记录左子结点
private Node left;
//记录右子结点
private Node right;
//记录key
private Key key;
//记录value
private Value value;
//初始化
public Node(Key key, Value value, Node left, Node right) {
this.key = key;
this.value = value;
this.left = left;
this.right = right;
}
}
/**
* 初始化
*/
public BinaryTree() {
this.size = 0;
}
/**
* 往树中插入一个键值对
*
* @param key
* @param value
*/
public void put(Key key, Value value) {
head = put(head, key, value);
}
/**
* 在指定树x上,添加一个键值对,并返回添加后的新树
*
* @param x
* @param key
* @param value
*/
public Node put(Node x, Key key, Value value) {
//判断根结点是否为空
if (x == null) {
size++;
return new Node(key, value, null, null);
} else {
//比较x 结点和key的大小
int cmp = key.compareTo(x.key);
//判断key 是否大于 当前结点的键,找出当前右子树
if (cmp > 0) {
x.right = put(x.right, key, value);
} else if (cmp < 0) {
//判断key 是否小于 当前结点的键,找出当前左子树
x.left = put(x.left, key, value);
} else {
//判断key 是否等于 当前结点的键,说明该键已经存在,则替换该值
x.value = value;
}
}
return x;
}
/**
* 根据key 返回value
*
* @param key
* @return
*/
public Value get(Key key) {
return get(head, key);
}
/**
* 从指定树中找出对应的值
*
* @param x
* @param key
* @return
*/
public Value get(Node x, Key key) {
if (x == null) {
return null;
}
int cmp = key.compareTo(x.key);
if (cmp > 0) {
x.value = get(x.right, key);
} else if (cmp < 0) {
x.value = get(x.left, key);
} else {
return x.value;
}
return x.value;
}
/**
* 删除key 对应的结点
*
* @param key
*/
public void delete(Key key) {
head = delete(head, key);
}
/**
* 删除指定结点x 中 的key,并返回删除后的树
*
* @param x
* @param key
* @return
*/
public Node delete(Node x, Key key) {
if (x == null) {
return null;
}
int cmp = key.compareTo(x.key);
if (cmp > 0) {
//新结点的key大于当前结点的key,继续找当前结点的右子结点
x.right = delete(x.right, key);
} else if (cmp < 0) {
//新结点的key小于当前结点的key,继续找当前结点的左子结点
x.left = delete(x.left, key);
} else {
//新结点的key等于当前结点的key,当前x就是要删除的结点
//1.如果当前结点的右子树不存在,则直接返回当前结点的左子结点
if (x.right == null) {
return x.left;
}
//2.如果当前结点的左子树不存在,则直接返回当前结点的右子结点
if (x.left == null) {
return x.right;
}
//3.当前结点的左右子树都存在
Node minNode = x.right;
//3.1找到右子树中最小的结点
while (minNode.left != null) {
minNode = minNode.left;
}
//3.2删除右子树中最小的结点
Node n = x.right;
while (n.left != null) {
if (n.left.left == null) {
n.left = null;
} else {
n = n.left;
}
}
//3.3让被删除结点的左子树称为最小结点minNode的左子树,让被删除结点的右子树称为最小结点minNode的右子树
minNode.left = x.left;
minNode.right = x.right;
//3.4让被删除结点的父节点指向最小结点minNode
x = minNode;
//个数-1
size--;
}
return x;
}
/**
* 获取元素个数
*
* @return
*/
public int size() {
return size;
}
/**
* 判断是否为空
*
* @return
*/
public boolean isEmpty() {
return size == 0;
}
/**
* 查找整个树中最小的键
*
* @return
*/
public Value min() {
return min(head).value;
}
/**
* 在指定树x 中找出最小键所在的结点
*
* @param x
* @return
*/
public Node min(Node x) {
//需要判断x 有没有左子结点,如果有,则继续向左找,如果没有,则x 就是最小键所在的结点
if (x.left != null) {
return min(x.left);
} else {
return x;
}
}
/**
* 查找整个树中最大的键
*
* @return
*/
public Value max() {
return max(head).value;
}
/**
* 在指定树x 中找出最大键所在的结点
*
* @param x
* @return
*/
private Node max(Node x) {
//判断x还有没有右子结点,如果有,则继续向有查找,如果没有,则x就是最大键所在的结点
if (x.right != null) {
return max(x.right);
} else {
return x;
}
}
/**
* 获取整个树中所有的键
*
* @return
*/
public Queue<Key> preErgodic() {
Queue<Key> keys = new Queue<>();
preErgodic(head, keys);
return keys;
}
/**
* 获取指定树x 的所有键,并放到keys 队列中
*
* @param x
* @param keys
* @return
*/
private void preErgodic(Node x, Queue<Key> keys) {
if (x == null) {
return;
}
//把当前结点的key放入到队列中;
keys.enqueue(x.key);
//递归遍历x结点的左子树
if (x.left != null) {
preErgodic(x.left, keys);
}
//递归调用x结点的右子树
if (x.right != null) {
preErgodic(x.right, keys);
}
}
/**
* 使用中序遍历获取所有的键
*
* @return
*/
public Queue<Key> midErgodic() {
Queue<Key> keys = new Queue<>();
midErgodic(head, keys);
return keys;
}
/**
* 使用中序遍历获取指定x中所有的键,并存放到key中
*
* @param x
* @param keys
* @returnz
*/
private void midErgodic(Node x, Queue<Key> keys) {
if (x == null) {
return;
}
先递归把左子树中的键放到keys中
if (x.left != null) {
midErgodic(x.left, keys);
}
//把当前结点x 的键放到keys中
keys.enqueue(x.key);
//再递归,把右子树的键放到keys中
if (x.right != null) {
midErgodic(x.right, keys);
}
}
/**
* 使用后序遍历,把整个树中所有的键返回
*
* @return
*/
public Queue<Key> afterErgodic() {
Queue<Key> keys = new Queue<>();
afterErgodic(head, keys);
return keys;
}
/**
* 使用后序遍历,把指定x树中所有的键放入到keys 中
*
* @param x
* @param keys
* @return
*/
private void afterErgodic(Node x, Queue<Key> keys) {
if (x == null) {
return;
}
//通过递归把左子树中所有的键放入到keys 中
if (x.left != null) {
afterErgodic(x.left, keys);
}
//通过递归右左子树中所有的键放入到keys 中
if (x.right != null) {
afterErgodic(x.right, keys);
}
//把x结点的键放入到keys中
keys.enqueue(x.key);
}
}