package tree;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
/**
* @Author zhw
* Version 1.0
* @Description BinaryTree
* Date 2021/8/16 18:13
**/
public class BinaryTree<Key extends Comparable<Key>, Value> {
/**
* @Description: 记录根节点
*/
private Node root;
/**
* @Description:记录树中元素的个数
*/
private int N;
/**
* @Description: 内部节点类
*/
private 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;
}
}
/**
* @Description: 获取树中元素的个数
* @return: int
*/
public int size() {
return N;
}
/**
* @param key key
* @param value value
* @Description: 向树中加入元素key-value
* @return: void
*/
public void put(Key key, Value value) {
root = put(root, key, value);
}
/**
* @param x x
* @param key key
* @param value value
* @Description: 向指定的树x中添加key-value,并返回添加元素后新的树
* @return: tree.BinaryTree<Key, Value>.Node
*/
private Node put(Node x, Key key, Value value) {
//如果x子树为空
if (null == x) {
N++;
return new Node(key, value, null, null);
}
//如果x子树不为空
//比较x节点的键和key的大小
int result = key.compareTo(x.key);
if (result > 0) {
//如果key大于x节点的键,则继续找x节点的右子树
x.right = put(x.right, key, value);
} else if (result < 0) {
//如果key小于x节点的键,则继续找x节点的左子树
x.left = put(x.left, key, value);
} else {
//如果key等于x节点的值,则替换x节点的值为value即可
x.value = value;
}
return x;
}
/**
* @param key key
* @Description: 查询树中指定key对应的value
* @return: Value
*/
public Value get(Key key) {
return get(root, key);
}
/**
* @param x x
* @param key key
* @Description: 从指定的树x中,查找对应key的值
* @return: Value
*/
private Value get(Node x, Key key) {
//x树为null
if (null == x) {
return null;
}
//x树不为null
//比较key和x节点的键的大小
int result = key.compareTo(x.key);
if (result > 0) {
//如果key大于x节点的键,则继续找x节点的右子树
return get(x.right, key);
} else if (result < 0) {
//如果key小于x节点的键,则继续找x节点的左子树
return get(x.left, key);
} else {
//如果key等于x节点的键,就找到了键为key的节点,只需要返回value即可
return x.value;
}
}
/**
* @param key key
* @Description: 删除树中key对应的value
* @return: void
*/
public void delete(Key key) {
delete(root, key);
}
/**
* @param x x
* @param key key
* @Description: 删除指定树中key对应的value,并返回删除后的新树
* @return: tree.BinaryTree<Key, Value>.Node
*/
private Node delete(Node x, Key key) {
//x树为null
if (null == x) {
return null;
}
//x树不为null
int result = key.compareTo(x.key);
if (result > 0) {
//如果key大于x节点的键,则继续找x节点的右子树
x.right = delete(x.right, key);
} else if (result < 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 node = x.right;
while (node.left != null) {
if (node.left.left == null) {
node.left = null;
} else {
//变换n节点即可
node = node.left;
}
}
//让x节点的左子树成为minNode的左子树
minNode.left = x.left;
//让x节点的右子树成为minNode的右子树
minNode.right = x.right;
//让x节点的父节点指向minNode
x = minNode;
}
return x;
}
/**
* @Description: 查找整个树中最小的键
* @return: Key
*/
public Key getMinKey() {
return getMinKey(root).key;
}
/**
* @param x x
* @Description: 在指定树中找出最小键所在的节点
* @return: tree.BinaryTree<Key, Value>.Node
*/
private Node getMinKey(Node x) {
//判断x还有没有左子节点,如果有,则继续项向左找
if (null != x.left) {
return getMinKey(x.left);
} else {
//如果没有,则x就是最小键所在的结点
return x;
}
}
/**
* @Description: 查找整个树的最大的键
* @return: Key
*/
public Key getMaxKey() {
return getMaxKey(root).key;
}
/**
* @param x x
* @Description: 在指定树中找出最大键所在的节点
* @return: tree.BinaryTree<Key, Value>.Node
*/
private Node getMaxKey(Node x) {
//判断x还有没有右子节点,如果有,则继续向右找
if (null != x.right) {
return getMaxKey(x.right);
} else {
//如果没有,则x键就是最大键所在的节点
return x;
}
}
/**
* @Description: 先序遍历获取整个树中所有的键
* @return: java.util.List<Key>
*/
public List<Key> preErgodic() {
List<Key> keys = new LinkedList<>();
preErgodic(root, keys);
return keys;
}
/**
* @param x x
* @param keys keys
* @Description: 先序遍历获取指定树x的所有键,并放到keys队列中
* @return: void
*/
private void preErgodic(Node x, List<Key> keys) {
if (null == x) {
return;
}
//把x节点的key放入到keys中
keys.add(x.key);
//递归遍历x节点的左子树
if (x.left != null) {
preErgodic(x.left, keys);
}
//递归遍历x节点的右子树
if (x.right != null) {
preErgodic(x.right, keys);
}
}
/**
* @Description: 中序遍历获取整个树中所有的键
* @return: java.util.List<Key>
*/
public List<Key> midErgodic() {
List<Key> keys = new LinkedList<>();
midErgodic(root, keys);
return keys;
}
/**
* @param x x
* @param keys keys
* @Description: 中序遍历获取指定树x的所有键,并放到keys队列中
* @return: void
*/
private void midErgodic(Node x, List<Key> keys) {
if (null == x) {
return;
}
//递归遍历x节点的左子树
if (x.left != null) {
midErgodic(x.left, keys);
}
//把x节点的key放入到keys中
keys.add(x.key);
//递归遍历x节点的右子树
if (x.right != null) {
midErgodic(x.right, keys);
}
}
/**
* @Description: 后序遍历获取整个树中所有的键
* @return: java.util.List<Key>
*/
public List<Key> afterErgodic() {
List<Key> keys = new LinkedList<>();
afterErgodic(root, keys);
return keys;
}
/**
* @param x x
* @param keys keys
* @Description: 后序遍历获取指定树x的所有键,并放到keys队列中
* @return: void
*/
private void afterErgodic(Node x, List<Key> keys) {
if (null == x) {
return;
}
//递归遍历x节点的左子树
if (x.left != null) {
afterErgodic(x.left, keys);
}
//递归遍历x节点的右子树
if (x.right != null) {
afterErgodic(x.right, keys);
}
//把x节点的key放入到keys中
keys.add(x.key);
}
/**
* @Description: 宽度优先遍历,使用层序遍历获取整个树中的所有键
* @return: java.util.List<Key>
*/
public List<Key> layerErgodic() {
//定义两个集合,分别存储树中的键和树中的节点
List<Key> keys = new LinkedList<>();
List<Node> nodes = new ArrayList<>();
//默认往集合中存入根节点
nodes.add(root);
while (!nodes.isEmpty()) {
//从队列中弹出一个节点,把key放入到集合中
Node node = nodes.get(0);
keys.add(node.key);
if (node.left != null) {
//判断当前结点还有没有左子结点,如果有,则放入到nodes中
nodes.add(node.left);
}
if (node.right != null) {
//判断当前结点还有没有右子结点,如果有,则放入到nodes中
nodes.add(node.right);
}
}
return keys;
}
/**
* @Description: 获取整个树的最大深度
* @return: int
*/
public int maxDepth() {
return maxDepth(root);
}
/**
* @param x x
* @Description: 获取指定树的最大深度
* @return: int
*/
private int maxDepth(Node x) {
if (null == x) {
return 0;
}
//左子树的最大深度
int maxL = 0;
//右子树的最大深度
int maxR = 0;
//计算x节点左子树的最大深度
if (x.left != null) {
maxL = maxDepth(x.left);
}
//计算x节点右子树的最大深度
if (x.right != null) {
maxR = maxDepth(x.right);
}
return maxL > maxR ? maxL + 1 : maxR + 1;
}
}
数据结构-Java-二叉树
最新推荐文章于 2024-10-12 17:55:45 发布