构建二叉树:左子结点小于根节点,右子结点大于根节点
// 二叉树代码
public class BinaryTree<Key extends Comparable<Key>, Value> {
//记录根结点
private Node root;
//记录树中元素的个数
private int N;
//获取树中元素的个数
public int size() {
return N;
}
//向树中添加元素key-value
public void put(Key key, Value value) {
root = put(root, key, value);
}
//向指定的树x中添加key-value,并返回添加元素后新的树
private Node put(Node x, Key key, Value value) {
if (x == null) {
N++;
return new Node(key, value, null, null);
}
int cmp = key.compareTo(x.key);
if (cmp > 0) {
x.right = put(x.right, key, value);
} else if (cmp < 0) {
x.left = put(x.left, key, value);
} else {
x.value = value;
}
return x;
}
//查询树中指定key对应的value
public Value get(Key key) {
return get(root, key);
}
//从指定的树x中,查找key对应的值
public Value get(Node x, Key key) {
if (x == null) {
return null;
}
int cmp = key.compareTo(x.key);
if (cmp > 0) {
return get(x.right, key);
} else if (cmp < 0) {
return get(x.left, key);
} else {
return x.value;
}
}
// 删除树中key对应的value
public void delete(Key key) {
root = delete(root, key);
}
// 删除指定树x中的key对应的value,并返回删除后的新树
public Node delete(Node x, Key key) {
if (x == null) {
return null;
}
int cmp = key.compareTo(x.key);
if (cmp > 0) {
x.right = delete(x.right, key);
} else if (cmp < 0) {
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.当前结点的左右子树都存在
//3.1找到右子树中最小的结点
Node minNode = x.right;
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
N--;
return x;
}
public Queue<Key> preErgodic() {
Queue<Key> keys = new Queue<>();
preErgodic(root, keys);
return keys;
}
//使用前序遍历,把指定树x中的所有键放入到keys队列中
private void preErgodic(Node x, Queue<Key> keys) {
if (x == null) {
return;
}
keys.enqueue(x.key);
//2.找到当前结点的左子树,如果不为空,递归遍历左子树
if (x.left != null) {
preErgodic(x.left, keys);
}
//3.找到当前结点的右子树,如果不为空,递归遍历右子树
if (x.right != null) {
preErgodic(x.right, keys);
}
}
//使用中序遍历,把指定树x中的所有键放入到keys队列中
private void midErgodic(Node x, Queue<Key> keys) {
if (x == null) {
return;
}
//2.找到当前结点的左子树,如果不为空,递归遍历左子树
if (x.left != null) {
preErgodic(x.left, keys);
}
keys.enqueue(x.key);
//3.找到当前结点的右子树,如果不为空,递归遍历右子树
if (x.right != null) {
preErgodic(x.right, keys);
}
}
//使用后序遍历,把指定树x中的所有键放入到keys队列中
private void afterErgodic(Node x, Queue<Key> keys) {
if (x == null) {
return;
}
//2.找到当前结点的左子树,如果不为空,递归遍历左子树
if (x.left != null) {
preErgodic(x.left, keys);
}
//3.找到当前结点的右子树,如果不为空,递归遍历右子树
if (x.right != null) {
preErgodic(x.right, keys);
}
keys.enqueue(x.key);
}
// 使用层序遍历得到树中所有的键
public Queue<Key> layerErgodic() {
Queue<Key> keys = new Queue<>();
Queue<Node> nodes = new Queue<>();
nodes.enqueue(root);
while (!nodes.isEmpty()) {
Node n = nodes.dequeue();
keys.enqueue(n.key);
if (n.left != null) {
nodes.enqueue(n.left);
}
if (n.right != null) {
nodes.enqueue(n.right);
}
}
return keys;
}
// 计算整个树的最大深度
public int maxDepth() {
return maxDepth(root);
}
//计算指定树x的最大深度
private int maxDepth(Node x) {
//1.如果根结点为空,则最大深度为0;
if (x == null) {
return 0;
}
int max = 0;
int maxL = 0;
int maxR = 0;
//2.计算左子树的最大深度;
if (x.left != null) {
maxL = maxDepth(x.left);
}
//3.计算右子树的最大深度;
if (x.right != null) {
maxR = maxDepth(x.right);
}
//4.当前树的最大深度=左子树的最大深度和右子树的最大深度中的较大者+1
max = maxL > maxR ? maxL + 1 : maxR + 1;
return max;
}
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;
}
}
public static void main(String[] args) {
/* BinaryTree<Integer, String> bt = new BinaryTree<>();
bt.put(4, "二哈");
bt.put(1, "张三");
bt.put(3, "李四");
bt.put(5, "王五");
System.out.println(bt.size());
bt.put(1, "老三");
System.out.println(bt.get(1));
System.out.println(bt.size());
bt.delete(1);
System.out.println(bt.size());*/
BinaryTree<String, String> bt = new BinaryTree<>();
bt.put("E", "5");
bt.put("B", "2");
bt.put("G", "7");
bt.put("A", "1");
bt.put("D", "4");
bt.put("F", "6");
bt.put("H", "8");
bt.put("C", "3");
Queue<String> queue = bt.preErgodic();
System.out.print("先序遍历:");
for (String key : queue) {
System.out.printf(key + " ");
}
System.out.println();
queue = bt.layerErgodic();
for (String key : queue) {
System.out.print(key + " ");
}
System.out.println(bt.maxDepth());
}
}