首页 > 其他 > 详细

二叉树

时间:2020-07-24 00:43:31      阅读:98      评论:0      收藏:0      [点我收藏+]

1. 树的定义

技术分享图片

树的特点:

  • 每个结点有0个或者多个子结点
  • 没有父结点的结点为根节点
  • 每一个非根结点只有一个父结点
  • 每个结点及其后代结点整体上可以看做一棵树,称为当前结点的父结点的一个子树

2. 树的相关术语

  • 结点的度:一个结点含有的子树的个数称为结点的度(也可以理解为子结点的个数)
  • 叶结点:度为0的结点称为叶结点
  • 分支结点:与叶结点相反,度不为0的结点称为分支结点
  • 结点的层次:从根结点开始,根结点的层次为1,根的直接后继层次为2,以此类推
  • 树的度:树中所有结点的度的最大值
  • 树的深度:树中结点的最大层次

3. 二叉树的基本定义

? ? ? 二叉树就是度不超过2的树(每个结点多有两个子结点)

  • 满二叉树:一个二叉树,每一层的结点都达到最大值,则这个二叉树就是满二叉树
    技术分享图片

  • 完全二叉树:叶节点只能出现在下层和次下层,并且下面一层的结点都集中在该层左边的若干位置的二叉树
    技术分享图片

4. 二叉树的API设计

技术分享图片

5.二叉树的代码实现

public class BinaryTree <Key extends Comparable<Key>,Value>{
    //记录根结点
    private Node root;
    private int N;

    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 int size(){
        return N;
    }
    //向树中添加元素key-value
    public void put(Key key,Value value){
        root = put(root,key,value);
    }
    //向指定树X中添加元素key-value
    public Node put(Node x,Key key,Value value){
        //如果x子树为空
        if (x == null){
            N++;
            return new Node(key,value,null,null);
        }
        //如果X子树不为空
        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);
    }
    //从指定树中查询key对应的值
    public Value get(Node x ,Key key){
        //x树为null
        if (x == null){
            return null;
        }
        //x树不为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){
        delete(root,key);
    }
    //删除指定树中key对应的value,并返回删除后的新树
    public Node delete(Node x,Key key){
        N--;
        //x树为null
        if (x == null){
            return null;
        }
        //x树不为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 {
            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 n = x.right;
            while (n.left!=null){
                if (n.left.left==null){
                    n.left = null;
                }else {
                    n = n.left;
                }
            }
            minNode.left = x.left;
            minNode.right = x.right;
            x = minNode;
        }
        return null;
    }
}

6.二叉树的遍历

1. 前序遍历

? ? ? 先访问根结点,然后再访问左子树,后访问右子树

2. 前序遍历代码实现
    //获取整个树中所有的键
    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;
        }
        //把x结点的key放入到keys中
        keys.enqueue(x.key);
        //递归遍历x结点的左子树
        if (x.left!=null){
            preErgodic(x.left,keys);
        }
        //递归遍历x结点的右子树
        if (x.right!=null){
            preErgodic(x.right,keys);
        }
    }
3. 中序遍历

? ? ? 先访问左子树,中间访问根节点,后访问右子树

4. 中序遍历代码实现
    public Queue<Key> midErgodic(){
        Queue<Key> keys = new Queue<>();
        midErgodic(root,keys);
        return null;
    }
    public 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);
        }
    }

5. 后序遍历

? ? ? 先访问左子树,再访问右子树,后访问根节点

6. 后序遍历代码实现
    public Queue<Key> afterErgodic(){
        Queue<Key> keys = new Queue<>();
        afterErgodic(root,keys);
        return keys;
    }

    public void afterErgodic(Node x,Queue<Key> keys){
        if (x==null){
            return;
        }
        if (x.left!=null){
            afterErgodic(x.left,keys);
        }
        if (x.right!=null){
            afterErgodic(x.right,keys);
        }
        keys.enqueue(x.key);
    }
7. 层序遍历

? ? ? 所谓的层序遍历,就是从根节点(第一层)开始,依次向下,获取每一层所有结点的值

8. 层序遍历代码实现
    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;
    }

7.二叉树的最大深度代码实现

    public int maxDepth(){
        return maxDepth(root);
    }

    public int maxDepth(Node x){
        if (x ==null){
            return 0;
        }
        int max = 0;
        int maxL = 0;
        int maxR = 0;
        //计算左子树最大深度
        if (x.left!=null){
            maxL = maxDepth(x.left);
        }
        //计算右子树最大深度
        if (x.right!=null){
            maxR = maxDepth(x.right);
        }
        //比较左子树的最大深度和右子树的最大深度,取较大值
        max = maxL>maxR?maxL+1:maxR+1;
        return max;
    }

二叉树

原文:https://www.cnblogs.com/zuzuzu-code/p/13369185.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!