首页 > 其他分享 >用颜色标记法,实现树的前中后序遍历

用颜色标记法,实现树的前中后序遍历

时间:2023-06-30 19:57:04浏览次数:34  
标签:遍历 treeNode 标记 TreeNode 后序 coloredTreeNode ColoredTreeNode new stack

使用颜色标记法,实现树的前中后序遍历

package algorithm;

import java.util.*;
import java.util.function.BiConsumer;

/**
 * 树的前中后序遍历 - 颜色标记法
 */
public class TreeTraversal {
    // white - 未访问过的节点
    private static final int WHITE = 0;
    // red - 访问过的节点
    private static final int RED = 0;
    private static final EnumMap<TraversalStrategy, BiConsumer<ColoredTreeNode, Stack<ColoredTreeNode>>> strategyHandler = new EnumMap<>(TraversalStrategy.class);

    public List<Integer> traversal(TreeNode root, TraversalStrategy strategy) {
        if (root == null) {
            return new ArrayList<>();
        }

        BiConsumer<ColoredTreeNode, Stack<ColoredTreeNode>> strategyConsumer = Optional.ofNullable(strategyHandler.get(strategy))
                .orElseThrow(() -> new RuntimeException("Unknown strategy: " + strategy));
        List<Integer> result = new ArrayList<>();
        Stack<ColoredTreeNode> stack = new Stack<>();
        stack.push(new ColoredTreeNode(WHITE, root));

        while (!stack.isEmpty()) {
            ColoredTreeNode curr = stack.pop();

            if (curr.color == WHITE) { // 如果节点未访问过
                // 使用对应策略,将根节点和左、右节点推入栈
                strategyConsumer.accept(curr, stack);
            } else {
                result.add(curr.treeNode.val);
            }
        }
        return result;
    }

    // 中序遍历
    BiConsumer<ColoredTreeNode, Stack<ColoredTreeNode>> inorderTraversal = (coloredTreeNode, stack) -> {
        // 中序遍历的顺序是: 左 -> 根 -> 右
        // 而栈是先进后出的结构,所以向栈中推数的顺序刚好相反,右 -> 根 -> 左
        if (coloredTreeNode.treeNode.right != null) {
            stack.push(new ColoredTreeNode(WHITE, coloredTreeNode.treeNode.right));
        }
        // curr节点已访问过,因此将颜色改为红色,再次推入栈中
        stack.push(coloredTreeNode.setColor(RED));
        if (coloredTreeNode.treeNode.left != null) {
            stack.push(new ColoredTreeNode(WHITE, coloredTreeNode.treeNode.left));
        }
    };

    // 前序遍历
    BiConsumer<ColoredTreeNode, Stack<ColoredTreeNode>> preorderTraversal = (coloredTreeNode, stack) -> {
        // 前序遍历的顺序是: 根 -> 左 -> 右
        // 而栈是先进后出的结构,所以向栈中推数的顺序刚好相反,右 -> 左 -> 根
        if (coloredTreeNode.treeNode.right != null) {
            stack.push(new ColoredTreeNode(WHITE, coloredTreeNode.treeNode.right));
        }
        if (coloredTreeNode.treeNode.left != null) {
            stack.push(new ColoredTreeNode(WHITE, coloredTreeNode.treeNode.left));
        }
        stack.push(coloredTreeNode.setColor(RED));
    };

    // 后序遍历
    BiConsumer<ColoredTreeNode, Stack<ColoredTreeNode>> postorderTraversal = (coloredTreeNode, stack) -> {
        // 后序遍历的顺序是: 左 -> 右 -> 根
        // 因此入栈顺序相反,是 根 -> 右 -> 左
        stack.push(coloredTreeNode.setColor(RED));
        if (coloredTreeNode.treeNode.right != null) {
            stack.push(new ColoredTreeNode(WHITE, coloredTreeNode.treeNode.right));
        }
        if (coloredTreeNode.treeNode.left != null) {
            stack.push(new ColoredTreeNode(WHITE, coloredTreeNode.treeNode.left));
        }
    };

    {
        // 定义不同遍历策略需要使用的栈处理方式
        strategyHandler.put(TraversalStrategy.INORDER, inorderTraversal);
        strategyHandler.put(TraversalStrategy.PREORDER, preorderTraversal);
        strategyHandler.put(TraversalStrategy.POSTORDER, postorderTraversal);
    }

    public enum TraversalStrategy {
        INORDER, // 中序
        PREORDER, // 前序
        POSTORDER // 后序
    }

    public static class ColoredTreeNode {
        // 树节点的颜色
        int color;
        // 被包装的树节点
        TreeNode treeNode;

        public ColoredTreeNode(int color, TreeNode treeNode) {
            this.color = color;
            this.treeNode = treeNode;
        }

        public ColoredTreeNode setColor(int color) {
            this.color = color;
            return this;
        }
    }

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

        public TreeNode() {
        }

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

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

 

标签:遍历,treeNode,标记,TreeNode,后序,coloredTreeNode,ColoredTreeNode,new,stack
From: https://www.cnblogs.com/rain-quiet/p/17517695.html

相关文章

  • 二叉树-前序遍历-leetcode222
    给你一棵完全二叉树的根节点root,求出该树的节点个数。完全二叉树的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第h层,则该层包含1~2h个节点。示例1:输入:root=[1,2,3......
  • 深入学习 GC 算法 - 标记清除算法
    博主介绍:✌博主从事应用安全和大数据领域,有8年研发经验,5年面试官经验,Java技术专家✌......
  • JS 数组遍历的方法
    <!DOCTYPEhtml><htmllang="zh-cn"><head><metacharset="UTF-8"><title></title></head><body><script>vara=[1,2,3,4,5,6];varb=a.some(function(ele,index,arr){console.......
  • JS for...in 遍历语句
    for...in语句用于对数组或者对象的属性进行循环操作。for(变量in对象){   在此执行代码}这里的“变量”用来指定变量,指定的变量可以是数组元素,也可以是对象的属性。 举个例子:<!DOCTYPEhtml><metacharset="UTF-8"><script>varx;varzoon=newArray();zoon[0]="......
  • 36. 图的遍历
    一、深度优先搜索  深度优先搜索(DepthFirstSerch,DFS)类似于树的先序遍历。深度优先遍历,从初始节点出发,初始访问节点可能有多个邻接节点,深度优先遍历的策略就是首先访问第一个邻接节点,然后在以这个被访问的邻接节点作为初始节点,访问它的第一个邻接节点。我们可以这样理解:每次都......
  • 代码审计——目录遍历详解
    01漏洞描述目录遍历,即利用路径回溯符“../”跳出程序本身的限制目录实现下载任意文件。例如Web应用源码目录、Web应用配置文件、敏感的系统文(/etc/passwd、/etc/paswd)等。一个正常的Web功能请求为http://www.test.com/lownload.php?file=test.php。如果Web应用存在路径遍历漏洞,则......
  • 代码随想录算法训练营第十六天| 找树左下角的值 路径总和 从中序与后序遍历序列
    找树左下角的值1,层序遍历,较为简单:1intfindBottomLeftValue_simple(TreeNode*root){2intresult=0;3if(!root)returnresult;4queue<TreeNode*>selected;5selected.push(root);67while(!selected.empty())8{9......
  • 遍历Json
    privatevoidSetShpFcSaveC5s(ShpFcSavemodel){if(string.IsNullOrWhiteSpace(model.C5)==false){JsonDocumentdocument=JsonDocument.Parse(model.C5);foreach(JsonElementjsonElementindocument.RootElement.EnumerateArray())......
  • Python.re正则表达式的标记
    标记方式在Python的re模块中,有以下几种标记(flags)可用于修改正则表达式的匹配行为:re.I(或re.IGNORECASE):忽略大小写匹配。例如,正则表达式[a-z]+将匹配小写字母字符串,而使用re.I标记后,它将匹配大小写混合或大写字母字符串。re.M(或re.MULTILINE):多行模式匹配。默认情况下,正......
  • 图的遍历——DFS, BFS(邻接矩阵,邻接表)——C语言描述
    图的遍历——DFS,BFS(邻接矩阵,邻接表)——C语言描述目录图的遍历——DFS,BFS(邻接矩阵,邻接表)——C语言描述0测试用例框架1图的深度优先遍历(DFS)1.1邻接矩阵(1)数据结构(2)代码(3)测试用例(4)打印结果1.2邻接表(1)数据结构(2)代码(3)测试用例(4)结果2图的广度度优先遍历(BFS)2.1队列(1)数据结构......