树的介绍及对应操作(基础篇)

树的介绍及对应操作(基础篇)

基本概念

​ 树是一种抽象的数据类型,用来模拟具有树状结构性质的数据集合。它是由n(n >= 0)个有限节点通过连接它们的边组成一个具有层次关系的集 合。n = 0时称为空树;n > 0时,有且仅有一个节点被称为根节点(Root),如果n = 1,树只有根节点一个节点。

​ 树的特点是层次结构,根节点在最上层,叶节点在最下层。每个节点都有一个子树,每个子树又是一个新的节点。节点的度是指其拥有的子树数量。

​ 树的种类有二叉树、平衡二叉树、红黑树、AVL树、B树、B+树、Trie树等。它们分别具有不同的性质和用途,如二叉树每个节点最多有两个子节点,平衡二叉树保持树的平衡以提高查找效率,红黑树是一种自平衡的二叉查找树等。

​ 总之,树是一种重要的数据结构,它可以用来组织和管理数据,还可以实现各种算法操作。

操作

先序·中序·后序遍历(递归)

按层遍历

判断相等树

判断镜面树

二叉树的最大深度

用先序数组和中序数组重建一棵树

二叉树按层遍历搜集节点

判断平衡二叉树

判断搜索二叉树

判断完全二叉树

判断满二叉树

能否组成路径和

搜集达标路径和

二叉树序列化和反序列化

n叉树序列化和反序列化

求最大距离

求树的最大宽度

返回该节点的后继节点

先序·中序·后序遍历(递归)
public static void Traver(Node head){
        if(head == null){
            return;
        }
        System.out.print(head.val + " ");//先序
        Traver(head.left);
    	//中序
        Traver(head.right);
    	//后序
    }
按层遍历
public static void levelTraver(Node head){
        if(head == null){
            return;
        }
        Queue<Node> queue = new LinkedList<>();
        queue.add(head);
        while (!queue.isEmpty()){
            Node cur = queue.poll();
            System.out.print(cur.val+" ");
            if(cur.left != null){
                queue.add(cur.left);
            }
            if(cur.right != null){
                queue.add(cur.right);
            }
        }
    }
判断相等树
public static boolean isSameTree(Node n1,Node n2){
        if(n1 == null ^ n2 == null){
            return false;
        }
        if(n1 == null && n2 == null){
            return true;
        }
        return n1.val == n2.val && isSameTree(n1.left,n2.left) && 							isSameTree(n1.right,n2.right);
    }
判断镜面树
public static boolean isMirror(Node head){
        if(head == null){
            return true;
        }
        return isMirrorMethod(head.left,head.right);
    }
public static boolean isMirrorMethod(Node n1,Node n2){
        if(n1 == null ^ n2 == null){
            return false;
        }
        if(n1 == null && n2 == null){
            return true;
        }
        return n1.val == n2.val && isSameTree(n1.left,n2.right) 							&& isSameTree(n1.right,n2.left);
    }
二叉树的最大深度
public static int MaxDepth(Node head){
        if(head == null){
            return 0;
        }
        return Math.max(MaxDepth(head.left),
                        MaxDepth(head.right)) + 1;
    }
用先序数组和中序数组重建一棵树
public static TreeNode buildTree2(int[] pre, int[] in) {
        if (pre == null || in == null || pre.length != in.length) {
            return null;
        }
        HashMap<Integer,Integer> valueIndexMap = new HashMap<>();
        for (int i = 0; i < in.length; i++) {
            valueIndexMap.put(in[i],i);
        }

        return f2(pre, 0, pre.length - 1, in, 0, in.length - 1,valueIndexMap);
    }
    public static TreeNode f2(int[] pre, int L1, int R1, int[] in, int L2, int R2, HashMap<Integer,Integer> valueIndexMap) {
        if (L1 > R1) {
            return null;
        }
        TreeNode head = new TreeNode(pre[L1]);
        if (L1 == R1) {
            return head;
        }
        int find = valueIndexMap.get(pre[L1]);
        head.left = f2(pre, L1+1, L1 + find-L2, in, L2, find - 1,valueIndexMap);
        head.right = f2(pre, L1 + find-L2 + 1, R1, in, find + 1, R2,valueIndexMap);
        return head;
    }
二叉树按层遍历搜集节点
public static List<List<Integer>> levelOrderBottom(TreeNode root){
        List<List<Integer>> ans = new LinkedList<>();
        if(root == null){
            return ans;
        }
        Queue<TreeNode> queue = new LinkedList<>();
        queue.add(root);
        while (!queue.isEmpty()){
            int size = queue.size();
            List<Integer> curAns = new LinkedList<>();
            for (int i = 0; i < size; i++) {
                TreeNode curNode = queue.poll();
                curAns.add(curNode.val);
                if(curNode.left != null){
                    queue.add(curNode.left);
                }
                if(curNode.right != null){
                    queue.add(curNode.right);
                }
            }
            ans.add(0,curAns);
        }
        return ans;
    }
判断平衡二叉树
public static boolean isBalancedTree(TreeNode root){
        return process(root).isBalanced;
    }
    public static class Info{
        public boolean isBalanced;
        public int height;

        public Info(boolean isBalanced, int height) {
            this.isBalanced = isBalanced;
            this.height = height;
        }
    }
    public static Info process(TreeNode x){
        if(x == null){
            return new Info(true,0);
        }
        Info leftInfo = process(x.left);
        Info rightInfo = process(x.right);

        int height = Math.max(leftInfo.height,rightInfo.height) + 1;

        boolean isBalanced = leftInfo.isBalanced && rightInfo.isBalanced
                && Math.abs(leftInfo.height- rightInfo.height) < 2;
        return new Info(isBalanced,height);
    }
判断搜索二叉树

两种方法:

(1)中序遍历数组是严格递增的,是搜索二叉树

(2)递归

	public static class Info {
        public boolean isBST;
        public int max;
        public int min;

        public Info(boolean isBST, int max, int min) {
            this.isBST = isBST;
            this.max = max;
            this.min = min;
        }
    }

    public static Info process(TreeNode x) {
        if (x == null) {
            return null;
        }
        Info leftInfo = process(x.left);
        Info rightInfo = process(x.right);
        int max = x.val;
        int min = x.val;
        if (leftInfo != null) {
            max = Math.max(leftInfo.max, max);
            min = Math.min(leftInfo.min, min);
        }
        if (rightInfo != null) {
            max = Math.max(rightInfo.max, max);
            min = Math.min(rightInfo.min, min);
        }
        boolean isBST = true;
        if (leftInfo != null && !leftInfo.isBST) {
            isBST = false;
        }
        if (rightInfo != null && !rightInfo.isBST) {
            isBST = false;
        }
        boolean leftMaxLessX = leftInfo == null ? true : (leftInfo.max < x.val);
        boolean rightMinMoreX = rightInfo == null ? true : (rightInfo.min > x.val);

        if (!leftMaxLessX || !rightMinMoreX) {
            isBST = false;
        }
        

        return new Info(isBST, max, min);
    }
判断完全二叉树
	public static boolean isCBT1(Node head){
        if(head == null){
            return true;
        }
        LinkedList<Node> queue = new LinkedList<>();
        boolean leaf = false;
        Node l = null;
        Node r = null;
        queue.add(head);
        while (!queue.isEmpty()){
            head = queue.poll();
            l = head.left;
            r = head.right;
            if (
                    (leaf && (l != null) || (r != null))
                    ||
                    (l == null && r !=null)
            ){
                return false;
            }
            if(l != null){
                queue.add(l);
            }
            if(r != null){
                queue.add(r);
            }
            if(l == null && r == null){
                leaf = true;
            }
        }
        return true;
    }
判断满二叉树
	public static boolean isFBT(Node head){
        if(head == null) {
            return true;
        }
        Info all = process(head);
        return (1 << all.height) - 1 == all.nodes;
    }
    public static class Info{
        public int height;
        public int nodes;

        public Info(int height, int nodes) {
            this.height = height;
            this.nodes = nodes;
        }
    }
    public static Info process(Node head){
        if(head == null){
            return new Info(0,0);
        }
        Info leftInfo = process(head.left);
        Info rightInfo = process(head.right);
        int height = Math.max(leftInfo.height,rightInfo.height) + 1;
        int nodes = leftInfo.nodes + rightInfo.nodes + 1;
        return new Info(height,nodes);

    }
能否组成路径和
	public static boolean isSum = false;

    public static boolean hasPathSum(TreeNode root,int sum){
        if(root == null){
            return false;
        }
        isSum = false;
        process(root,0,sum);
        return isSum;
    }

    public static void process(TreeNode x,int preSum,int sum){
        if(x.left == null && x.right == null){
            if(x.val + preSum == sum){
                isSum = true;
            }
            return;
        }
        //非叶节点
        preSum += x.val;
        if(x.left != null){
            process(x.left,preSum,sum);
        }
        if(x.right != null){
            process(x.right,preSum,sum);
        }
    }
搜集达标路径和
	public static List<List<Integer>> pathSum(TreeNode root, int sum) {
        List<List<Integer>> ans = new ArrayList<>();
        if (root == null) {
            return ans;
        }
        ArrayList<Integer>  path = new ArrayList<>();
        process(root,path,0,sum,ans);
        return ans;
    }

    public static void process(TreeNode x, List<Integer> path, int preSum, int sum,
                               List<List<Integer>> ans) {
        if (x.left == null && x.right == null) {
            if (preSum + x.val == sum) {
                path.add(x.val);
                ans.add(copy(path));
                path.remove(path.size() - 1);
            }
            return;
        }
        //x是非叶节点
        path.add(x.val);
        preSum += x.val;
        if(x.left != null){
            process(x.left,path,preSum,sum,ans);
        }
        if(x.right != null){
            process(x.right,path,preSum,sum,ans);
        }
        path.remove(path.size() - 1);

    }

    public static List<Integer> copy(List<Integer> path) {
        List<Integer> ans = new ArrayList<>();
        for (Integer num : path) {
            ans.add(num);
        }
        return ans;
    }
二叉树序列化和反序列化
前序
	public static Queue<String> preSerial(Node head){
        Queue<String> ans = new LinkedList<>();
        pres(head,ans);
        return ans;
    }
    public static void pres(Node head,Queue<String> ans){
        if(head == null){
            ans.add(null);
        }else {
            ans.add(String.valueOf(head.value));
            pres(head.left, ans);
            pres(head.right, ans);
        }
    }
    public static Node buildByPreQueue(Queue<String> preList){
        if(preList == null || preList.size() == 0){
            return null;
        }
        return preb(preList);
    }
    public static Node preb(Queue<String> preList){
        String value = preList.poll();
        if(value == null){
            return null;
        }
        Node head = new Node(Integer.valueOf(value));
        head.left = preb(preList);
        head.right = preb(preList);
        return head;
    }
按层
	public static Queue<String> levelSerial(Node head){
        Queue<String> ans = new LinkedList<>();
        if(head == null){
            ans.add(null);
        }else {
            ans.add(String.valueOf(head.value));
            Queue<Node> queue = new LinkedList<>();
            queue.add(head);
            while (!queue.isEmpty()){
                head = queue.poll();
                if(head.left != null){
                    ans.add(String.valueOf(head.left.value));
                    queue.add(head.left);
                }else {
                    ans.add(null);
                }
                if(head.right != null){
                    ans.add(String.valueOf(head.right.value));
                    queue.add(head.right);
                }else {
                    ans.add(null);
                }
            }

        }
        return ans;
    }
    public static Node buildByLevelQueue(Queue<String> levelList){
        if(levelList == null || levelList.size() == 0){
            return null;
        }
        Node head = generateNode(levelList.poll());
        Queue<Node> queue = new LinkedList<>();
        if(head != null){
            queue.add(head);
        }
        Node node = null;
        while (!queue.isEmpty()){
            node = queue.poll();
            node.left = generateNode(levelList.poll());
            node.right = generateNode(levelList.poll());
            if(node.left != null){
                queue.add(node.left);
            }
            if(node.right != null){
                queue.add(node.right);
            }
        }
        return head;

    }
    public static Node generateNode(String val){
        if(val == null){
            return null;
        }
        return new Node(Integer.valueOf(val));
    }
n叉树序列化和反序列化
	public static class Node {
        public int val;
        public List<Node> children;

        public Node() {
        }

        public Node(int val) {
            this.val = val;
        }

        public Node(int val, List<Node> children) {
            this.val = val;
            this.children = children;
        }
    }

    public static class TreeNode {
        int val;
        TreeNode left;
        TreeNode right;

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

    class Codec{
        public TreeNode encode(Node root){
            if(root == null){
                return null;
            }
            TreeNode head = new TreeNode(root.val);
            head.left = en(root.children);
            return head;
        }

        public TreeNode en(List<Node> children){
            TreeNode head = null;
            TreeNode cur = null;
            for (Node child : children) {
                TreeNode tNode = new TreeNode(child.val);
                if(head == null){
                    head = tNode;
                }else {
                    cur.right = tNode;
                }
                cur = tNode;
                cur.left = en(child.children);
            }
            return head;
        }

        public Node decode(TreeNode root){
            if(root == null){
                return null;
            }
            return new Node(root.val,de(root.left));
        }
        public List<Node> de(TreeNode root){
            List<Node> children = new ArrayList<>();
            while (root != null){
                Node cur = new Node(root.val,de(root.left));
                children.add(cur);
                root = root.right;
            }
            return children;
        }
    }
求最大距离
public static int maxDistance1(Node head){
        return process(head).maxDistance;
    }

    public static class Info{
        public int maxDistance;
        public int height;

        public Info(int maxDistance, int height) {
            this.maxDistance = maxDistance;
            this.height = height;
        }
    }
    public static Info process(Node x){
        if (x == null){
            return new Info(0,0);
        }
        Info leftInfo = process(x.left);
        Info rightInfo = process(x.right);
        int height = Math.max(leftInfo.height,rightInfo.height) + 1;
        int p1 = leftInfo.maxDistance;
        int p2 = rightInfo.maxDistance;
        int p3 = leftInfo.height + rightInfo.height + 1;

        int maxDistance = Math.max(Math.max(p1,p2),p3);

        return new Info(maxDistance,height);
    }
求树的最大宽度
	public static int maxWidthUseMap(Node head){
        if(head == null){
            return 0;
        }
        Queue<Node> queue = new LinkedList<>();
        queue.add(head);
        Node curEnd = head;
        Node nextEnd = null;
        int max = 0;
        int curLevelNodes = 0;
        while (!queue.isEmpty()){
            Node cur = queue.poll();
            if (cur.left != null){
                queue.add(cur.left);
                nextEnd = cur.left;
            }
            if(cur.right != null){
                queue.add(cur.right);
                nextEnd = cur.right;
            }
            curLevelNodes++;
            if(cur == curEnd){
                max = Math.max(max,curLevelNodes);
                curLevelNodes = 0;
                curEnd = nextEnd;
            }
        }
        return max;
    }
返回该节点的后继节点
	public static class Node{
        public int value;
        public Node left;
        public Node right;
        public Node parent;

        public Node(int value) {
            this.value = value;
        }
    }
    public static Node getSuccessorNode(Node node){
        if(node == null){
            return node;
        }
        if(node.right != null){
            return getLeftMost(node.right);
        }else {
            Node parent = node.parent;
            while (parent != null && parent.right == node){
                node = parent;
                parent = node.parent;
            }
            return parent;
        }
    }
    public static Node getLeftMost(Node node){
        if(node == null){
            return node;
        }
        while (node.left != null){
            node = node.left;
        }
        return node;
    }
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值