【5.二叉树】

树的简介

树是一种非线性的数据结构,它是由n(n>=0)个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的

树的相关概念

结点的度:一个结点含有子树的个数称为该结点的度
树的度:一棵树中,所有结点度的最大值称为树的度
叶子结点或终端结点:度为0的结点称为叶结点
双亲结点或父结点:若一个结点含有子结点,则这个结点称为其子结点的父结点
孩子结点或子结点:一个结点含有的子树的根结点称为该结点的子结点
根结点:一棵树中,没有双亲结点的结点
结点的层次:从根开始定义起,根为第1层,根的子结点为第2层,以此类推
树的高度或深度:树中结点的最大层次

两种特殊的二叉树

  1. 满二叉树: 一棵二叉树,如果每层的结点数都达到最大值,则这棵二叉树就是满二叉树。也就是说,如果一棵二叉树的层数为K,且结点总数是 ,则它就是满二叉树。
  2. 完全二叉树: 完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树而引出来的。对于深度为K的,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从0至n-1的结点一一对应时称之为完全二叉树。 要注意的是满二叉树是一种特殊的完全二叉树。

二叉树的性质

  1. 若规定根结点的层数为1,则一棵非空二叉树的第i层上最多有 (i>0)个结点
  2. 若规定只有根结点的二叉树的深度为1,则深度为K的二叉树的最大结点数是 (k>=0)
  3. 对任何一棵二叉树, 如果其叶结点个数为 n0, 度为2的非叶结点个数为 n2,则有n0=n2+1
  4. 具有n个结点的完全二叉树的深度k为 上取整
  5. 对于具有n个结点的完全二叉树,如果按照从上至下从左至右的顺序对所有节点从0开始编号,则对于序号为i
    的结点有:
    若i>0,双亲序号:(i-1)/2;i=0,i为根结点编号,无双亲结点
    若2i+1<n,左孩子序号:2i+1,否则无左孩子
    若2i+2<n,右孩子序号:2i+2,否则无右孩子

二叉树的实现及相关OJ题目

package MyBinaryTree;
import java.awt.event.ItemEvent;
import java.util.*;

import sun.reflect.generics.tree.Tree;

public class MyBinaryTree {
    static class TreeNode {
        public char val;
        public TreeNode left;
        public TreeNode right;

        public TreeNode(char val) {
            this.val = val;
        }
    }

    public TreeNode root;

    public TreeNode creatTree() {
        TreeNode A = new TreeNode('A');
        TreeNode B = new TreeNode('B');
        TreeNode C = new TreeNode('C');
        TreeNode D = new TreeNode('D');
        TreeNode E = new TreeNode('E');
        TreeNode F = new TreeNode('F');
        TreeNode G = new TreeNode('G');
        TreeNode H = new TreeNode('H');
        A.left = B;
        A.right = C;
        B.left = D;
        B.right = E;
        C.left = F;
        C.right = G;
        E.right = H;
        this.root = A;
        return root;
    } // 创建二叉树  后面会以递归重新定义

    public void preOrder(TreeNode root) {
        if (root == null) {
            return;
        }
        System.out.println(root.val + " "); //打印root节点
        preOrder(root.left);
        preOrder(root.right);
    } // 前序遍历 根左右  递归

    public void inOrder(TreeNode root) {
        if (root == null) {
            return;
        }
        inOrder(root.left);
        System.out.println(root.val + " ");
        inOrder(root.right);
    } //中序遍历 左根右    递归

    public void PostOrder(TreeNode root) {
        if (root == null) {
            return;
        }
        PostOrder(root.left);
        PostOrder(root.right);
        System.out.println(root.val + " ");
    } // 后序遍历 左右根 递归

    public int size(TreeNode root) {
        if (root == null) {
            return 0;
        }
        int leftNode = size(root.left);
        int rightNode = size(root.right);
        return leftNode + rightNode + 1;
    } // 算树总结点 递归思路

    public int getLeafNodeCount(TreeNode root) {
        if (root == null) {
            return 0;
        }
        if (root.right == null && root.left == null) {
            return 1;
        }
        int leftLeaf = getLeafNodeCount(root.left);
        int rightLeaf = getLeafNodeCount(root.right);
        return leftLeaf + rightLeaf;
    } //获取叶子节点个数 递归

    public int getKLevelNOdeCount(TreeNode root, int k) {
        if (root == null) {
            return 0;
        }
        if (k == 1) {
            return 1;
        }
        int kLN = getKLevelNOdeCount(root.left, k - 1);
        int kRN = getKLevelNOdeCount(root.right, k - 1);
        return kLN + kRN;
    } //获取树第K层节点个数 递归

    public int getHight(TreeNode root) {
        if (root == null) {
            return 0;
        }
        int leftHight = getHight(root.left);
        int rightHight = getHight(root.right);
        return Math.max(leftHight, rightHight) + 1;
    } //获取树的高度

    public TreeNode find(TreeNode root, int val) {
        if (root == null) {
            return null;
        }
        if (root.val == val) {
            return root;
        }
        TreeNode leftTree = find(root.left, val);
        if (leftTree != null) {
            return leftTree;
        }
        TreeNode rightTree = find(root.right, val);
        if (rightTree != null) {
            return rightTree;
        }
        return null;
    } // 查找树中值为val的元素

    public boolean isSameTree(TreeNode p, TreeNode q) {
        if ((p == null && q != null) || (q == null && p != null)) {
            return false;
        }
        if (q == null && p == null) {
            return true;
        }
        if (p.val != q.val) {
            return false;
        }
        return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);

    } //判断两树是否相同

    public TreeNode invertTree(TreeNode root) {
        if (root == null) {
            return null;
        }
        TreeNode temp = root.right;
        root.right = root.left;
        root.left = temp;
        invertTree(root.left);
        invertTree(root.right);
        return root;
    } //翻转二叉树

    public boolean isBalanced(TreeNode root) {
        if (root == null) {
            return true;
        }
        int lH = getHight(root.left);
        int rH = getHight(root.right);
        int H = Math.abs(lH - rH);
        if (H > 1) {
            return false;
        }
        return
                isBalanced(root.left) &&
                        isBalanced(root.right);

    } //判断平衡树 时间复杂度 O(N^2)

    public int isBalanced2(TreeNode root) {
        if (root == null) {
            return 0;
        }
        int leftHight = getHight(root.left);
        int rightHight = getHight(root.right);
        if (leftHight >= 0 && rightHight >= 0 && Math.abs(leftHight - rightHight) <= 1) {
            return Math.max(leftHight, rightHight) + 1;
        } else {
            return -1;
        }
    }

    public boolean isSymmetric(TreeNode root) {
        return isSymmetricChild(root.right, root.left);

    }

    public boolean isSymmetricChild(TreeNode lefttree, TreeNode righttree) {
        if ((lefttree == null && righttree != null) || (lefttree != null && righttree == null)) {
            return false;
        }
        if (lefttree == null && righttree == null) {
            return true;
        }
        if (lefttree.val != righttree.val) {
            return false;
        }
        return isSymmetricChild(lefttree.left, righttree.right)
                && isSymmetricChild(lefttree.right, righttree.left);
    }

    public void levelOrder(TreeNode root) {
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while (!queue.isEmpty()) {
            TreeNode cur = queue.poll();
            System.out.println(cur.val + " ");
            if (cur.left != null) {
                queue.offer(cur.left);
            }
            if (cur.right != null) {
                queue.offer(cur.right);
            }
        }

    } //层序遍历

    public List<List<Integer>> levelOrder1(TreeNode root) {
        List<List<Integer>> list = new ArrayList<>();
        if (root == null) {
            return list;
        }
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while (!queue.isEmpty()) {
            int size = queue.size();
            List<Integer> tmp = new ArrayList<>();
            while (size != 0) {
                TreeNode cur = queue.poll();
                //System.out.println(cur.val+" ");
                //tmp.add(cur.val);
                size--;
                if (cur.left != null) {
                    queue.offer(cur.left);
                }
                if (cur.right != null) {
                    queue.offer(cur.right);
                }
            }
            list.add(tmp);
        }
        return list;
    } //层序遍历2

    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if (root == null) {
            return null;
        }
        if (root == p || root == q) {
            return root;
        }
        TreeNode left = lowestCommonAncestor(root.left, p, q);
        TreeNode right = lowestCommonAncestor(root.right, p, q);
        if (left != null && right != null) {
            //p,q节点在根的左右两边
            return root;
        } else if (left != null) {
            //p,q节点都在左边 且 有一个节点是公共节点
            return left;
        } else if (right != null) {
            //p,q节点都在左边 且 有一个节点是公共节点
            return right;
        }
        return null;
    } //返回最近公共祖先 也可以用两个栈实现

    public int i = 0;

    public TreeNode buildTree(int[] inorder, int[] postorder) {
        i = postorder.length - 1;
        return buildTreeChild(inorder, postorder, 0, postorder.length - 1);

    }

    public TreeNode buildTreeChild(int[] inorder, int[] postorder, int inbegin, int inend) {

        if (inbegin > inend) {
            return null;
        }
        if (inorder.length == 0) {
            return null;
        }
        if (inorder.length == 1) {
            //TreeNode root = new TreeNode(postorder[0]);
        }
        //TreeNode root = new TreeNode(postorder[i]);
        int rootIndex = findIndex(inorder, inbegin, inend, postorder[i]);
        i--;
        root.right = buildTreeChild(inorder, postorder, rootIndex + 1, inend);
        root.left = buildTreeChild(inorder, postorder, inbegin, rootIndex - 1);
        return root;

    }

    private int findIndex(int[] inorder, int inbegin, int inend, int key) {
        for (int i = inbegin; i <= inend; i++) {
            if (inorder[i] == key) {
                return i;
            }
        }
        return -1;
    }

    public String tree2str(TreeNode root) {
        if (root == null) {
            return null;
        }
        StringBuilder sb = new StringBuilder();
        tree2strChile(root, sb);

        return sb.toString();
    }

    public void tree2strChile(TreeNode t, StringBuilder sb) {
        if (t == null) {
            return;
        }
        sb.append(t.val);
        if (t.left != null) {
            sb.append("(");
            tree2strChile(t.left, sb);
            sb.append(")");
        } else {
            if (t.right != null) {
                sb.append("()");

            } else {
                return;
            }
        }
        if (t.right == null) {
            return;
        } else {
            sb.append("(");
            tree2strChile(t.right, sb);
            sb.append(")");
        }


    } //根据二叉树创建字符串

    public boolean isCompleteTree(TreeNode root) {
        if (root == null) {
            return true;
        }
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while (!queue.isEmpty()) {
            TreeNode cur = queue.poll();
            if (cur != null) {
                queue.offer(cur.left);
                queue.offer(cur.right);
            } else {
                break;
            }
        }
        while (!queue.isEmpty()) {
            TreeNode tmp = queue.poll();
            if (tmp != null) {
                return false;
            }
        }
        return true;
    } //判断是否是完全二叉树

    public void perOderNor(TreeNode root) {
        if (root == null) {
            return;
        }
        TreeNode cur = root;
        Deque<TreeNode> stack = new ArrayDeque<>();
        while (cur != null || !stack.isEmpty()) {
            while (cur != null) {
                stack.push(cur);
                System.out.println(cur.val + " ");
                cur = cur.left;
            }
            TreeNode top = stack.pop();
            cur = top.right;
        }


    } //前序遍历 循环

    public void inOrderNor(TreeNode root)  {
        if (root == null) {
            return;
        }
        TreeNode cur = root;
        Deque<TreeNode> stack = new ArrayDeque<>();
        while (cur != null || !stack.isEmpty()) {
            while (cur != null) {
                stack.push(cur);
                cur = cur.left;
            }
            TreeNode top = stack.pop();
            System.out.println(top.val + " ");
            cur = top.right;
        }


    } //中序遍历 循环

    public void PostOrderNor(TreeNode root){
        List<Integer> list = new ArrayList<>();
        if (root == null) {
            return;
        }
        TreeNode cur = root;
        TreeNode prev = null;
        Deque<TreeNode> stack = new ArrayDeque<>();
        while (cur != null || !stack.isEmpty()) {
            while (cur != null) {
                stack.push(cur);
                cur = cur.left;
            }
            TreeNode top = stack.peek() ;
            if(top.right == null || top.right == prev){
                System.out.println(top.val+" ");
                stack.pop();
                prev = top;
            } else {
                cur = top.right;
            }

        }
    } //后续遍历 循环

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. 二叉树的递归遍历: 二叉树的递归遍历是指通过递归方法遍历二叉树的各个节点,按照某种次序访问每个节点。常见的二叉树遍历方式有前序遍历、中序遍历和后序遍历。 2. 二叉树的非递归遍历: 二叉树的非递归遍历是指通过循环等非递归方法遍历二叉树的各个节点,按照某种次序访问每个节点。非递归遍历需要借助栈来实现,常见的二叉树遍历方式有前序遍历、中序遍历和后序遍历。 3. 二叉树的层次遍历: 二叉树的层次遍历是指按照从上到下、从左到右的顺序遍历每一层节点。常用的方法是使用队列来实现,首先将根节点入队列,然后依次出队列,并将其左右子节点入队列,直到队列为空。 4. 输出二叉树上所有叶节点: 二叉树上的叶节点是指没有子节点的节点。可以通过递归方式,对每个节点进行判断,如果该节点没有左右子节点,则将该节点输出。 5. 求二叉树的高度: 二叉树的高度是指从根节点到叶节点最长路径上经过的边数。可以通过递归方式求解,从左右子树中选取较大的一个加上根节点即可。 6. 二叉树层序生成算法二叉树层序生成算法是指按照从上到下、从左到右的顺序依次生成每个节点。可以使用队列来实现,首先将根节点入队列,然后依次出队列,并根据当前节点生成其左右子节点,将其入队列,直到生成完所有节点。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值