8.二叉树复习

构建二叉树:左子结点小于根节点,右子结点大于根节点

// 二叉树代码
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());
    }

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值