遍历树,找出所有叶子路径

一、示例:

树的结构:

示例中自己构建了图片中的这棵树:

树节点模型:

public class TreeNode {
    String value;
    List<TreeNode> children;

    public TreeNode() {
        children = new ArrayList<>();
    }

    public TreeNode(String value) {
        this.value = value;
        children = new ArrayList<>();
    }

    @Override
    public String toString() {
        // TODO Auto-generated method stub
        return value;
    }
}

构建树:

// 创建一棵树
TreeNode root = new TreeNode("A");
// 第二层
root.children.add(new TreeNode("B"));
root.children.add(new TreeNode("C"));
// 第三层
root.children.get(0).children.add(new TreeNode("D"));
root.children.get(0).children.add(new TreeNode("E"));
root.children.get(1).children.add(new TreeNode("F"));
root.children.get(1).children.add(new TreeNode("H"));
root.children.get(1).children.add(new TreeNode("G"));
// 第四层
root.children.get(0).children.get(1).children.add(new TreeNode("I"));

二、遍历方式

提供三种方式进行遍历:

① 递归形式的深度优先遍历:

/**
     * 深度优先遍历(递归方式) --- 树(Tree)
     */
    public void recurTree(TreeNode root) {
        List<List<String>> result = new ArrayList<>();
        List<String> path = new ArrayList<>();
        path.add(root.value);
        findPath(result, root, path);
        System.out.println(result);
    }

    private void findPath(List<List<String>> result, TreeNode node, List<String> path) {
        if (node.children == null || node.children.size() <= 0) {
            result.add(path);
            return;
        }

        for (int i = 0; i < node.children.size(); i++) {
            TreeNode child = node.children.get(i);
            List<String> cPath = new ArrayList<>();
            cPath.addAll(path);
            cPath.add(child.value);
            findPath(result, child, cPath, target);
        }
    }

② 非递归的深度优先遍历

/**
     * 深度优先遍历(非递归方式) ----- 查找树的所有叶子路径
     *
     * @param root
     *            根节点
     * @return 叶子路径的集合
     */
    public List<List<TreeNode>> dfsTree(TreeNode root) {
        Stack<TreeNode> nodeStack = new Stack<>();
        Stack<List<TreeNode>> pathStack = new Stack<>();
        List<List<TreeNode>> result = new ArrayList<>();
        nodeStack.push(root);
        ArrayList<TreeNode> arrayList = new ArrayList<>();
        arrayList.add(root);
        pathStack.push(arrayList);

        while (!nodeStack.isEmpty()) {
            TreeNode curNode = nodeStack.pop();
            List<TreeNode> curPath = pathStack.pop();

            if (curNode.children == null || curNode.children.size() <= 0) {
                result.add(curPath);
            } else {
                int childSize = curNode.children.size();
                for (int i = childSize - 1; i >= 0; i--) {
                    TreeNode node = curNode.children.get(i);
                    nodeStack.push(node);
                    List<TreeNode> list = new ArrayList<>(curPath);
                    list.add(node);
                    pathStack.push(list);
                }
            }
        }
        return result;
    }

3. 广度优先遍历,遍历所有叶子路径

/**
     * 广度优先遍历 ---- 查找树的所有叶子路径
     *
     * @param root
     *            根节点
     * @return 叶子路径的集合
     */
    public List<List<TreeNode>> bfsTree(TreeNode root) {
        Queue<TreeNode> nodeQueue = new LinkedList<>();
        Queue<List<TreeNode>> qstr = new LinkedList<>();
        List<List<TreeNode>> result = new ArrayList<>();
        nodeQueue.add(root);
        ArrayList<TreeNode> arrayList = new ArrayList<>();
        qstr.add(arrayList);

        while (!nodeQueue.isEmpty()) {
            TreeNode curNode = nodeQueue.remove();
            List<TreeNode> curList = qstr.remove();

            if (curNode.children == null || curNode.children.size() <= 0) {
                curList.add(curNode);
                result.add(curList);
            } else {
                for (int i = 0; i < curNode.children.size(); i++) {
                    TreeNode treeNode = curNode.children.get(i);
                    nodeQueue.add(treeNode);
                    List<TreeNode> list = new ArrayList<>(curList);
                    list.add(curNode);
                    qstr.add(list);
                }
            }
        }

        return result;
    }

三种方式的输出:

深度优先遍历(递归):[[A, B, D], [A, B, E, I], [A, C, F], [A, C, H], [A, C, G]]
广度优先遍历:[[A, B, D], [A, C, F], [A, C, H], [A, C, G], [A, B, E, I]]
深度优先遍历(非递归):[[A, B, D], [A, B, E, I], [A, C, F], [A, C, H], [A, C, G]]

三、总结

  示例是查找树的所有叶子节点,举一反三,如果我们是查找树中满足某个条件的路径,也是非常容易了。比如下面中查找 “ E ” 的分支:

public void recurTree(TreeNode root) {
        List<List<String>> result = new ArrayList<>();
        List<String> path = new ArrayList<>();
        path.add(root.value);
        findPath(result, root, path, "E");
        System.out.println(result);
    }

    private void findPath(List<List<String>> result, TreeNode node, List<String> path, String target) {
        if (target.equals(node.value)) {
            result.add(path);
            return;
        }

        if (node.children == null || node.children.size() <= 0) {
            return;
        }

        for (int i = 0; i < node.children.size(); i++) {
            TreeNode child = node.children.get(i);
            List<String> cPath = new ArrayList<>();
            cPath.addAll(path);
            cPath.add(child.value);
            if (result.size() > 0)
                break;
            findPath(result, child, cPath, target);
        }
    }

输出:

[[A, B, E]]

原文地址:https://www.cnblogs.com/aimqqroad-13/p/10238093.html

时间: 2024-10-13 07:12:45

遍历树,找出所有叶子路径的相关文章

【算法】求二叉树各路径结点之和并找出最大值的路径

说在前面的话 最近没事将大学里的<数据结构>(严蔚敏,吴伟民著)一书重拾温习,受益颇多,才发现工作之中诸多经验问题都找到了理论支撑. 当时觉得没用的书,现在只能嘲笑当时得多low... 现在依然很low... --! 事件背景 因实际工作中,遇到一个关于权重的问题,需要将数据关系中最大权重的路径找到,然后就想到了<数据结构>中的DFS... 此事勾起了我码砖的激情,让我本已平静的心再次荡漾... 为了简单说明这个问题,我就拿个二叉树的模型来叙述一下我要达成的目标 CASE Exam

九度1035 -树 - 找出直系亲属

这道题目一开始我还以为是并查集,后来发现比并查集简单的多,就是一个家谱树,然后找到两个节点之间的深度差. #include<stdio.h> int data[30]; void make_set(){ for(int i=0;i<30;i++) data[i]=-1; } int find(int a,int b){ int re=1; while(data[a]!=-1){ if(data[a]==b)return re; a=data[a]; re++; } return -1;

字典树 找出单词文件中出现次数前十的单词

import java.io.*; import java.util.*; /** * 不区分大小写 */ class TrieNode{ TrieNode[] next = new TrieNode[26]; // 只有小写字母的字典树 0存放a 1存放b ... 25存放z int count = 0;//字母出现的次数 int wordCount = 0;// 单词出现的次数 char currentChar; public TrieNode(char word) { this.curre

如何通过pid快速找出进程的路径

[[email protected] Desktop]$ top top - 09:35:06 up 32 min,  2 users,  load average: 1.49, 1.56, 1.32Tasks: 290 total,   1 running, 287 sleeping,   0 stopped,   2 zombieCpu(s):  9.9%us,  4.7%sy,  0.0%ni, 80.2%id,  5.2%wa,  0.0%hi,  0.0%si,  0.0%stMem:

数据结构与算法学习之路:迷宫问题——回溯思想找出所有路径

今天小伙伴和我说之前写的那个迷宫问题有些问题,我就改了改,感觉之前写的东西思路也不清晰,也比较乱,就重新写了一篇--别在意哈- 一.迷宫问题描述: 给定一个迷宫,以及起点和终点,通过设计算法,找到一条可以到达终点的路径.解决以后,想办法找到最短路径和所有路径. 二.解决方法: 1.找到一条可达的路径并不难,只要设定方向,然后每个点都去找一个可以走的方向一直向可行方向走就是了. 2.找到最短路径.要找到最短路径,可以尝试广度优先算法--BFS.BFS找图中一点到另一点的最短路径还是很方便的(没有权

在线性级别时间内找出无序序列中的第k个元素

在一个无序序列中找出第k个元素,对于k很小或者很大时可以采取特殊的方法,比如用堆排序来实现 .但是对于与序列长度N成正比的k来说,就不是一件容易的事了,可能最容易想到的就是先将无序序列排序再遍历即可找出第k个元素.由于任何基于比较的排序算法不可能用少于Θ(N lgN)次比较来实现将所有元素排序,所以采用排序的方法的时间复杂度是线性对数级别的. 我们可以借鉴快速排序中将序列划分的思想来实现平均情况下线性级别的算法,算法实现如下: 1 public class KthElement { 2 3 pr

(转)在二元树中找出和为某一值的所有路径,java版本

摘自:http://www.cnblogs.com/qi09/archive/2011/05/24/2055643.html 4.在二元树中找出和为某一值的所有路径 题目:输入一个整数和一棵二元树. 从树的根结点开始往下访问一直到叶结点所经过的所有结点形成一条路径. 打印出和与输入整数相等的所有路径. 例如输入整数22 和如下二元树 10 / \ 5 12 /\ 4 7 则打印出两条路径:10, 12 和10, 5, 7. 二元树节点的数据结构定义为: struct BinaryTreeNode

python3实现在二叉树中找出和为某一值的所有路径

在二叉树中找出和为某一值的所有路径请写一个程序创建一棵二叉树,并按照一定规则,输出二叉树根节点到叶子节点的路径.规则如下:1.从最顶端的根结点,到最下面的叶子节点,计算路径通过的所有节点的和,如果与设置的某一值的相同,那么输出这条路径上的所有节点.2.从根节点遍历树时,请请按照左到右遍历,即优先访问左子树的节点.二叉树创建规则:从上到下一层一层的,按照从左到右的顺序进行构造输入"10,5,12,4,7"值,构造的树如下:1) 102) 10      /    5 3) 10     

深度优先遍历多叉树结构,输出叶子路径

树结构的深度优先遍历是应用中常见的问题 在实际项目中,多叉树出现的比较普遍,常用来存储类似字典词条的路径信息. 多叉树对于在一个序列中找到前缀匹配的所有路径是可行的选择,例如找到一段文字中所有前缀匹配的词条(中国人民解放军为例,有中,中国,中国人,中国人民,中国人民解放军等匹配词条). 构造一棵包含所有中文词条的字典树,可以通过深度优先遍历快速解析出这些前缀匹配的词条,树的每一个节点都是一个汉字,尔从根节点出发的路径是存储的中文词条. 以下的代码是一段示例,它的遍历会输出所有的叶子节点. 树结构