树的两种遍历

1 树的序遍历

前序遍历、中序遍历、后序遍历

1.1 遍历方式

都有点抽象,需要结合代码和画图来看

  1. 递归遍历
  2. 非递归遍历:都是用栈来解决
    1. 前序遍历
      • 用一个栈,先进右再进左
    2. 中序遍历
      • 用一个栈,先进左,左出,再进右
    3. 后序遍历
      • 用两个栈,一个栈和前序遍历反着来,出的元素进另一个栈,进完之后全打印
      • 用一个栈,先解决左边的,再解决右边的。

1.2 代码实现

java 复制代码
public class RecursiveTraversalBT {
    public static class Node {
        public int val;
        public Node left;
        public Node right;
        public Node(int val){
            this.val = val;
        }
    }

    // 递归遍历
    public static void pre1(Node head) {
        if (head == null) {
            return;
        }
        System.out.print(head.val + " ");
        pre1(head.left);
        pre1(head.right);
    }

    public static void in1(Node head) {
        if (head == null) {
            return;
        }
        in1(head.left);
        System.out.print(head.val + " ");
        in1(head.right);
    }

    public static void pos1(Node head) {
        if (head == null) {
            return;
        }
        pos1(head.left);
        pos1(head.right);
        System.out.print(head.val + " ");
    }

    // 非递归遍历(栈)
    public static void pre2(Node head) {
        if (head != null) {
            Stack<Node> stack = new Stack<>();
            stack.push(head);
            while (!stack.isEmpty()) {
                head = stack.pop();
                System.out.print(head.val + " ");
                if (head.right != null) {
                    stack.push(head.right);
                }
                if (head.left != null) {
                    stack.push(head.left);
                }
            }
        }
    }

    public static void in2(Node head) {
        if (head != null) {
            Stack<Node> stack = new Stack<>();
            while (!stack.isEmpty() || head != null) {
                if (head != null) {
                    stack.push(head);
                    head = head.left;
                }else {
                    head = stack.pop();
                    System.out.print(head.val + " ");
                    head = head.right;
                }
            }
        }
    }

    public static void pos2(Node head) {
        if (head != null) {
            Stack<Node> stack1 = new Stack<>();
            Stack<Node> stack2 = new Stack<>();
            stack1.push(head);
            while (!stack1.isEmpty()){
                head = stack1.pop();
                stack2.push(head);
                if (head .left != null) {
                    stack1.push(head.left);
                }
                if (head .right != null) {
                    stack1.push(head.right);
                }
            }
            while (!stack2.isEmpty()) {
                System.out.print(stack2.pop().val + " ");
            }
        }
    }

    // 后序遍历的第三种写法(只用一个栈)
    public static void pos3(Node head) {
        if (head != null) {
            Stack<Node> stack = new Stack<>();
            stack.push(head);
            Node help = null;
            while (!stack.isEmpty()) {
                help = stack.peek();
                if (help.left !=null && head != help.left && head != help.right){
                    stack.push(help.left);
                } else if (help.right != null && head != help.right) {
                    stack.push(help.right);
                }else {
                    System.out.print(stack.pop().val + " ");
                    head = help;
                }
            }
        }

    }
    
    public static void main(String[] args) {
        Node head = new Node(1);
        head.left = new Node(2);
        head.right = new Node(3);
        head.left.left = new Node(4);
        head.left.right = new Node(5);
        head.right.left = new Node(6);
        head.right.right = new Node(7);

        pos2(head);
        System.out.println();
        pos3(head);
        System.out.println();

    }
}

2 树的层遍历

2.1 遍历方式

树的最宽层有几个节点?

  1. 借助Map来查找
    1. 定义一个队列和一个HashMap,都把头节点放进去,其中Map中存放的是当前节点和其对应的层数
    2. 每次弹出一个节点,就把这个节点的左右子节点都放进队列和对应的Map
    3. 如果还没到下一层,那么当前层的节点数就要加一
    4. 如果到了下一层,就把上一层的节点数和之前层的节点数比较
    5. 返回节点数最多的层的节点数
  2. 只用队列
    1. 定义一个当前层的最左节点,一个下一层的最左节点
    2. 当弹出的节点等于当前层最左节点时,记录当前层节点数并与之前层的最大节点数比较,哪个大留哪个
    3. 这个时候就要进入下一次,所以当前层节点数置为0,当前层最左节点置为下一层最左节点

4.2.2 代码实现

java 复制代码
public class TreeMaxWidth {
    public static class Node {
        public int val;
        public Node left;
        public Node right;
        public Node(int val) {
            this.val = val;
            left = null;
            right = null;
        }
    }

    public static int maxWidthUseMap(Node head) {
        if (head == null) {
            return 0;
        }
        Queue<Node> queue = new LinkedList<>();
        queue.add(head);
        HashMap<Node, Integer> hashMap = new HashMap<>();
        hashMap.put(head, 1);
        int curLevelNodes = 0;
        int curLevel = 1;
        int max = 0;
        while (!queue.isEmpty()) {
            Node cur = queue.poll();
            int curNodeLevel = hashMap.get(cur);
            if (cur.left != null) {
                queue.add(cur.left);
                hashMap.put(cur.left, curNodeLevel + 1);
            }
            if (cur.right != null) {
                queue.add(cur.right);
                hashMap.put(cur.right, curNodeLevel + 1);
            }
            if (curLevel == curNodeLevel) {
                curLevelNodes++;
            }else {
                max = Math.max(max, curLevelNodes);
                curLevel++;
                curLevelNodes = 1;
            }
        }
        max = Math.max(max, curLevelNodes);
        return max;
    }

    public static int maxWidthNoMap (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 void main(String[] args) {
        Node head = new Node(1);
        head.left = new Node(2);
        head.right = new Node(3);
        head.left.left = new Node(4);
        head.left.right = new Node(5);
        head.right.left = new Node(6);
        head.right.right = new Node(7);
        head.left.right.left = new Node(8);
        head.right.left.right = new Node(9);
        
        System.out.println(maxWidthNoMap(head));
    }
}
相关推荐
源代码•宸17 小时前
分布式缓存-GO(分布式算法之一致性哈希、缓存对外服务化)
开发语言·经验分享·分布式·后端·算法·缓存·golang
It's now17 小时前
Spring AI 基础开发流程
java·人工智能·后端·spring
计算机毕设VX:Fegn089517 小时前
计算机毕业设计|基于springboot + vue图书商城系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·课程设计
夕颜11118 小时前
BeeAI 框架学习记录
后端
极市平台18 小时前
骁龙大赛-技术分享第5期(上)
人工智能·经验分享·笔记·后端·个人开发
程序员爱钓鱼19 小时前
Node.js 编程实战:路由处理原理与实践
后端·node.js·trae
hhzz20 小时前
Spring Boot整合Activiti的项目中实现抄送功能
java·spring boot·后端
Victor35621 小时前
Netty(7)如何实现基于Netty的TCP客户端和服务器?
后端
Victor35621 小时前
Netty(8)什么是Netty的ChannelPipeline和ChannelHandler?
后端
乘风!1 天前
NSSM启动tomcat部署Java程序
java·服务器·后端·tomcat