获取树深度

求树的深度 随机给定一棵树,求树的深度 阅读详情

概要:
使用BFS(广度优先搜索)、DFS(深度优先搜索)的递归和非递归方式获取树深度。

代码:
Util类:

package com.example.study.util;

import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Stack;
import java.util.stream.Collectors;

/**
 * 获取树深度
 * 注:若最深一层只有null元素,该层不计入深度
 */
public class TreeDepthUtil {
    private static final Byte FLAG = 1;

    /**
     * dfs的递归实现获取树深度
     *
     * @param root       根节点
     * @param childField 子节点列表字段名称
     * @param <T>        节点类型
     * @return 树深度
     */
    public static <T> int getTreeDepthByDfsWithRecursion(T root, String childField) {
        if (root == null || !StringUtils.hasText(childField)) {
            return 0;
        }
        List<Integer> depth = new ArrayList<>(1);
        depth.add(0);
        // 这里只是需要一个标志,表示当前路径上的点,所以用byte减少内存占用
        Stack<Byte> stack = new Stack<>();
        doGetTreeDepthByDfs(root, childField, stack, depth);
        return depth.get(0);
    }

    private static <T> void doGetTreeDepthByDfs(T parent, String childField, Stack<Byte> stack, List<Integer> depth) {
        stack.push(FLAG);
        depth.set(0, Math.max(depth.get(0), stack.size()));
        Collection<T> childs = (Collection<T>) getFieldValue(parent, childField);
        if (CollectionUtils.isEmpty(childs)) {
            stack.pop();
            return;
        }
        for (T child : childs) {
            if (child == null) {
                continue;
            }
            doGetTreeDepthByDfs(child, childField, stack, depth);
        }
        stack.pop();
    }

    /**
     * dfs的非递归(循环)实现获取树深度
     *
     * @param root       根节点
     * @param childField 子节点列表字段名称
     * @param <T>        节点类型
     * @return 树深度
     */
    public static <T> int getTreeDepthByDfsWithLoop(T root, String childField) {
        if (root == null || !StringUtils.hasText(childField)) {
            return 0;
        }
        Stack<Iterator> stack = new Stack<>();
        List<T> list = new ArrayList<>();
        list.add(root);
        Iterator<T> iterator = list.iterator();
        Iterator<T> emptyIterator = (Iterator<T>) Collections.emptyList().iterator();
        int depth = 0;
        while (true) {
            while (!iterator.hasNext() && !stack.isEmpty()) {
                iterator = stack.pop();
            }
            if (!iterator.hasNext() && stack.isEmpty()) {
                break;
            }
            stack.push(iterator);
            depth = Math.max(depth, stack.size());
            T next = iterator.next();
            Collection<T> childs = (Collection<T>) getFieldValue(next, childField);
            if (childs != null) {
                childs = childs.stream().filter(o -> o != null).collect(Collectors.toList());
            }
            iterator = childs == null ? emptyIterator : childs.iterator();
        }
        return depth;
    }

    /**
     * bfs的递归实现获取树深度
     *
     * @param root       根节点
     * @param childField 子节点列表字段名称
     * @param <T>        节点类型
     * @return 树深度
     */
    public static <T> int getTreeDepthByBfsWithRecursion(T root, String childField) {
        if (root == null || !StringUtils.hasText(childField)) {
            return 0;
        }
        List<T> parents = new ArrayList<>();
        parents.add(root);
        List<Integer> depth = new ArrayList<>(1);
        depth.add(0);
        doGetTreeDepthByBfs(parents, childField, depth);
        return depth.get(0);
    }

    private static <T> void doGetTreeDepthByBfs(Collection<T> parents, String childField, List<Integer> depth) {
        if (parents.isEmpty()) {
            return;
        }
        depth.set(0, depth.get(0) + 1);
        readChilds(parents, childField);
        doGetTreeDepthByBfs(parents, childField, depth);
    }

    /**
     * bfs的非递归(循环)实现获取树深度
     *
     * @param root       根节点
     * @param childField 子节点列表字段名称
     * @param <T>        节点类型
     * @return 树深度
     */
    public static <T> int getTreeDepthByBfsWithLoop(T root, String childField) {
        if (root == null || !StringUtils.hasText(childField)) {
            return 0;
        }
        List<T> parents = new ArrayList<>();
        parents.add(root);
        int depth = 0;
        while (!parents.isEmpty()) {
            depth++;
            readChilds(parents, childField);
        }
        return depth;
    }


    private static <T> void readChilds(Collection<T> parents, String childField) {
        List<T> allChilds = new ArrayList<>();
        for (T parent : parents) {
            Collection<T> childs = (Collection<T>) getFieldValue(parent, childField);
            if (childs == null) {
                continue;
            }
            allChilds.addAll(childs.stream().filter(o -> o != null).collect(Collectors.toList()));
        }
        parents.clear();
        parents.addAll(allChilds);
    }

    /**
     * 获取字段值
     *
     * @param element   待获取值的对象
     * @param fieldName 字段名称
     * @param <T>       对象类型
     * @return 字段值
     */
    private static <T> Object getFieldValue(T element, String fieldName) {
        try {
            Field field = element.getClass().getDeclaredField(fieldName);
            field.setAccessible(true);
            return field.get(element);
        } catch (IllegalAccessException exception) {
            throw new RuntimeException("no permission to read field [" + fieldName + "]!");
        } catch (NoSuchFieldException e) {
            throw new RuntimeException("field [" + fieldName + "] not exists!");
        }
    }
}

测试;
部门信息类:

package com.example.study.entity;

import lombok.Data;

import java.util.List;

/**
 * 部门实体类
 */
@Data
public class DepartmentEntity {
    /**
     * 部门id
     */
    private Integer id;
    /**
     * 部门名称
     */
    private String name;
    /**
     * 上级部门id
     */
    private Integer parentId;

    /**
     * 子部门列表
     */
    private List<DepartmentEntity> childs;
}

测试类:

package com.example.study.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.example.study.entity.DepartmentEntity;

import java.util.List;

public class Test {
    public static void main(String[] args) {
        String data = "[ { \"id\": 0, \"name\": \"部门0(根部门)\", \"parentId\": -1 }, { \"id\": 1, \"name\": \"部门1\", \"parentId\": 0 }, { \"id\": 2, \"name\": \"部门2\", \"parentId\": 0 }, { \"id\": 3, \"name\": \"部门3\", \"parentId\": 0 }, { \"id\": 4, \"name\": \"部门4\", \"parentId\": 2 }, { \"id\": 5, \"name\": \"部门5\", \"parentId\": 2 }, { \"id\": 6, \"name\": \"部门6\", \"parentId\": 3 }, { \"id\": 7, \"name\": \"部门7\", \"parentId\": 3 }, { \"id\": 8, \"name\": \"部门8\", \"parentId\": 6 }, { \"id\": 9, \"name\": \"部门9\", \"parentId\": 7 }, { \"id\": 10, \"name\": \"部门10\", \"parentId\": 9 }, { \"id\": 11, \"name\": \"部门11\", \"parentId\": 9 } ]";
        List<DepartmentEntity> departments = JSONArray.parseArray(data, DepartmentEntity.class);
        DepartmentEntity root = departments.stream().filter(o -> o.getParentId() == -1).findFirst().get();
        ListTreeConvertUtil.listToTree(departments, root, "parentId", "id", "childs");
        System.out.println(JSON.toJSONString(root));

        DepartmentEntity tmp = new DepartmentEntity();
        root.getChilds().add(1, null);
        root.getChilds().get(3).getChilds().get(0).getChilds().get(0).setChilds(null);
        root.getChilds().get(3).getChilds().get(1).getChilds().get(0).getChilds().get(1).getChilds().add(null);
        root.getChilds().get(3).getChilds().get(1).getChilds().get(0).getChilds().get(1).getChilds().add(tmp);

        System.out.println(JSON.toJSONString(root));
        System.out.println(TreeDepthUtil.getTreeDepthByDfsWithRecursion(root, "childs"));
        System.out.println(TreeDepthUtil.getTreeDepthByDfsWithLoop(root, "childs"));
        System.out.println(TreeDepthUtil.getTreeDepthByBfsWithRecursion(root, "childs"));
        System.out.println(TreeDepthUtil.getTreeDepthByBfsWithLoop(root, "childs"));

    }
}

测试结果:

{"childs":[{"childs":[],"id":1,"name":"部门1","parentId":0},{"childs":[{"childs":[],"id":4,"name":"部门4","parentId":2},{"childs":[],"id":5,"name":"部门5","parentId":2}],"id":2,"name":"部门2","parentId":0},{"childs":[{"childs":[{"childs":[],"id":8,"name":"部门8","parentId":6}],"id":6,"name":"部门6","parentId":3},{"childs":[{"childs":[{"childs":[],"id":10,"name":"部门10","parentId":9},{"childs":[],"id":11,"name":"部门11","parentId":9}],"id":9,"name":"部门9","parentId":7}],"id":7,"name":"部门7","parentId":3}],"id":3,"name":"部门3","parentId":0}],"id":0,"name":"部门0(根部门)","parentId":-1}
{"childs":[{"childs":[],"id":1,"name":"部门1","parentId":0},null,{"childs":[{"childs":[],"id":4,"name":"部门4","parentId":2},{"childs":[],"id":5,"name":"部门5","parentId":2}],"id":2,"name":"部门2","parentId":0},{"childs":[{"childs":[{"id":8,"name":"部门8","parentId":6}],"id":6,"name":"部门6","parentId":3},{"childs":[{"childs":[{"childs":[],"id":10,"name":"部门10","parentId":9},{"childs":[null,{}],"id":11,"name":"部门11","parentId":9}],"id":9,"name":"部门9","parentId":7}],"id":7,"name":"部门7","parentId":3}],"id":3,"name":"部门3","parentId":0}],"id":0,"name":"部门0(根部门)","parentId":-1}

6
6
6
6
Java实现二叉树最大深度 如果为空,说明二叉树为空树,深度为0。然后,我们使用递归的方式分别计算左子树和右子树的最大深度。最后,我们返回左子树和右子树中深度较大的值加1,即为二叉树的最大深度。要计算二叉树的最大深度,我们可以使用递归的方法。下面是一个使用Java编写的示例代码,可以计算二叉树的最大深度。希望这个示例代码能够帮助你理解如何使用Java实现求二叉树的最大深度。然后,我们创建了一个。方法中,我们创建了一个示例二叉树,并调用。在上述代码中,我们首先定义了一个。方法计算最大深度,然后输出结果。方法用于计算二叉树的最大深度。 阅读详情

相关推荐

PHP 树形结构构建与转换实战:实现 arrayToTree、treeToArray 及获取树深度

【代码】PHP实现树与数组的转换。

qq_39294511的博客 372

Java求树的深度(真的是树,而不是二叉树)#全网首发#

Java求树的深度(真的是树,而不是二叉树)#全网首发# 相信对于二叉树的递归求深度这个问题,我们已经非常熟悉。 那么对于树的递归求深度应该可以类似地使用二叉树的递归求深度的方法。 具体代码的实现 二叉树求深度(递归) int Tree::treeDepth(TNode *bt) { if (bt == NULL)return 0; // 计算左子树的深度 int a = treeDepth(bt.leftchild); // 计算右子树的深

m0_50859585的博客 1690

智能车小白也能懂:手把手教你用LM358和工字电感搭建电磁循迹模块(附PCB设计避坑)

本文详细介绍了如何利用LM358运放和工字电感搭建智能车电磁循迹模块,从电感选型、电路设计到PCB布局和焊接调试,提供全流程实战指南。特别针对新手常见问题,如信号干扰、电路饱和等,给出具体解决方案和参数配置,帮助智能车比赛爱好者快速掌握电磁循迹技术。

weixin_30307921的博客 401

项目算法: 计算树形结构的深度(层数)

项目算法: 计算树形结构的深度(层数) 今天在写项目的后台管理系统时,遇到一个需要算法的地方.即拖动某一节点到另一节点时,需要判断能否达到目标节点,且达到目标节点后需要计算新的level,而这两个地方都需要计算拖动的树形结构的深度(层数).抽象出来即是下图: 这里有两种思路写这个算法,一种是递归写法(简洁),另一种是非递归写法. 下面用js语言都列出来.写法1:以抽象图为例, 下面代码中的root即...

qq_43318840的博客 2022

CCS TMSC6748 报错Error connecting to the target: (Error -600 @ 0x0)

CCS TMSC6748 报错Error connecting to the target:(Error -600@ 0x0)

AS_the_deer1717的博客 6636

zynq+LWIP 裸机双网口实现(MIO+EMIO)+程序下载

芯片型号: ZYNQ: XC7Z010clg400开发软件:Vivado2022 + Xilinx Vitis 2022网卡芯片:RTL8211FDI(需要根据网口芯片型号修改对应的硬件配置代码。

thinking in 小宇宙 3408

java----求树的深度

问题描述 求一棵树的深度, 并返回这棵树的深度 解决思路 如果树为空树, 返回 0; 如果树不空, 求左子树的高度和右子树的高度并取其中的较大者作为子树的高度, 原树的高度就是 求出的较大者 + 1 (这个 1 是根节点所在的位置也算一层). max(leftHeightTree, rightHeightTree) + 1; 源代码 public int getHeight(TreeNode root) { if (root == null) { return .

m0_50527451的博客 1467

Keil MDK打开别人工程总报错?手把手教你修复‘找不到main.o’和‘未定义’的路径问题

本文详细解析Keil MDK工程移植时常见的'找不到main.o'和'未定义'编译错误,提供从路径修复到宏定义配置的完整解决方案。通过系统化的检查清单和预防措施,帮助开发者快速解决MDK工程迁移问题,提升嵌入式开发效率。

weixin_28724661的博客 399

获取二叉树的所有叶子节点、获取全树深度与左右子树深度求解:递归

树的左右子树深度 全树的深度 //因为我们现在能够不重复,不遗漏获取每一个节点,只有前中后序3种方法,所以,我们首先先写出 //先序递归获取树的深度 int hight = 0;//它可以在多个函数之间共享 //前序是根左右,我们把每一个树从root出发的树,可以看出左右两个子树 //无论我们如何遍历,我们前进到每一个节点都是潜在的根节点。 //我们可以认为每到一个新节点,就是到了一个新树, //如果说,我们对新节点的发现,我们就认为到了一个新层,那么我们累加 //记录就可以了 //我用level作为当前

weixin_45683301的博客 867

【AI概念】迁移学习 vs. 域自适应 vs. 域泛化|定义、核心原理、数学表达、易混淆点与工程选择建议|实际案例、工程实现细节、未来研究趋势、实际应用场景

大家好,我是爱酱。本篇将会详细梳理迁移学习(Transfer Learning)、域自适应(Domain Adaptation)、域泛化(Domain Generalization)三大常被混淆的核心概念,结合数学公式、典型算法与实际应用场景,帮助你厘清它们的本质区别、联系与工程意义。 注:本文章含大量数学算式、详细例子说明及大量代码演示,大量干货,建议先收藏再慢慢观看理解。新频道发展不易,你们的每个赞、收藏跟转发都是我继续分享的动力!

AI人工智能爱酱~你的AI学习好帮手~ 2469

OpenClaw实战:拒绝复制粘贴,用 xlsx 技能打通“带公式模板”的月报自动化

本文详解了如何利用 OpenClaw 框架搭载的 xlsx skill,解决 AI 自动化处理“带复杂公式与格式”Excel 月报时极易翻车的业务痛点。针对传统大模型粗暴写入导致模板报废的问题,OpenClaw 创新采用“双核微创”工作流:首先利用 pandas 高效清洗并聚合海量原始明细数据,随后切换至 openpyxl 将计算结果精准注入目标模板,完美保留原有的底色、边框与跨表动态公式。

我有一个梦想 151

获取XGBoost中树模型的最大深度

本文讲无论是否设置max_depth,怎么样查看XGBoost中各棵树模型的深度。 查阅XGBoost文档可以发现,XGBoost并未提供像sklearn一样的get_depth()方法 所以解决方法如下: 1、绘图、查看图像得出(不够自动化) import xgboost as xgb from sklearn.datasets import make_classification X,y = make_classification(random_state=99) # 上面的数据因人而异,这里构建的模

小白tree的博客 1778

【四足机器人项目实战】波士顿spot四足机器人机工程设计及实现分析

主要介绍了波士顿spot机器人的发展历史、四足机器人的硬件系统及电机执行器组成包括硬件系统、关节电机执行器,机载传感器机处理器及电气连接等。概述了四足机器人规划控制、感知、定位及局部地图的相关算法方向。

qq_35635374的博客 4997

数据结构:二叉树的二叉链表存储--Java实现

public class TwoLinkTree { // 内部节点类 public static class TreeNode { Object data; TreeNode left; TreeNode right; public TreeNode(Object data) { this.data = data; } public TreeNode(Obj

amorvos的专栏 1072

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

【数据结构之二叉树】二叉树的创建、遍历等操作

二叉树的基本操作: 1.创建二叉树 2.销毁二叉树 3.遍历二叉树:1)前序遍历 2)中序遍历 3)后序遍历 4)层次遍历 4.搜索二叉树 5.删除子叶 6.插入子叶 7.获取左/右子叶的值 8.获取树深度 9.获取叶子结点数 1.创建二叉树 这里创建的是链式存储结构的二叉树,包含数据域,左右两结点的指针域;在读取创建树时,以#代替空格,输入格式的规范为:以前序遍历的...

weixin_30662109的博客 242

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

对树的几个基本操作函数

//显示树中所有节点的值void show(tnode *root){ if (root) {  coutvalue  show(root->left);  show(root->right); }}//输入树的每层节点值void GetLayer(tnode*root,vector& v){ if (root == NULL)  return ; queue* > q; tnode *p

stevenzhou的专栏 708

实现一个通用的树形结构构建工具

树结构的生成在项目中应该都比较常见,比如部门结构树的生成,目录结构树的生成,但是大家有没有想过,如果在一个项目中有多个树结构,那么每一个都要定义一个生成方法显然是比较麻烦的,所以我们就想写一个通用的生成树方法,下面就来看下如何来写。

Jwasx的博客 1432

树

树的基本所有操作代码~ 树的遍历,计算树的深度,左子树,右子树等~

Win_Xin的博客 506

leetcode(543). Diameter of Binary Tree

problem Given a binary tree, you need to compute the length of the diameter of the tree. The diameter of a binary tree is the length of the longest path between any two nodes in a tree. This pa

qishi的博客 472

java实现树

实现一颗树,采用数组的存储方式,将树中的节点用Node类表示,方便与操作。 首先,整棵树的数组结构如下表所示,根节点的无父节点,用“-1”表示。 index Data parent 0 A -1 1 B 0 2 C 0 3 D 0 4 E 1 5 F 1 6 G 5

36ICE的博客 524

判断是否为平衡二叉树

最直接的做法,遍历每个结点,借助一个获取树深度的递归函数,根据该结点的左右子树高度差判断是否平衡,然后递归地对左右子树进行判断。 public classSolution { public boolean IsBalanced_Solution(TreeNode root) { if(root == null) { return true; ...

devcy的博客 810

决策树-构造注解树

注解树:将树中的信息添加到决策树图中。 Note:绘制图形的x轴有效范围是0.0到1.0,y轴有效范围也是0.0到1.0。def getNumLeafs(myTree): #获取叶节点树 numLeafs = 0 # firstStr = myTree.keys()[0] #mytree的第一个特征值 python2写法 first = list(myTree.ke

疯狂的兔子 584

数据结构和算法之判断是否是平衡二叉树

思路一: 1、遍历每个结点,借助一个获取树深度的递归函数 2、根据该结点的左右子树高度差判断是否平衡 缺点:从上往下遍历,时间复杂度高,会重复计算高度 思路二: 1、后序遍历,从下往上遍历,遍历左子树和右子树 2、递归的方法,求左子树和右子树的高度 3、每次在求出左子树和右子树的高度的时候比较一下两者之间的差值是否大于1 package com.zyblue.fastim.common.a...

多拉C梦 413

[剑指offer]平衡二叉树

思路: 遍历每个节点,借助一个获取树深度的递归函数,根据该节点的左右子树高度差判断是否平衡,然后递归地对左右子树进行判断。 实现: public class Solution { public boolean IsBalanced_Solution(TreeNode root) { return getDept(root) != -1; } private...

叽歪的博客 151

java算法比较两个二叉数是否相等_java实现二叉树查找,统计结点个数,统计树的深度及判断两棵树是否相等...

二叉树的建立在前面已经实现,现在只写子函数public bitreeNode searchNode(bitreeNode t,Object x){if(t!=null){if(t.getdata().equals(x)) //对根节点进行判断return t;else{bitreeNode lresult=searchNode(t.getlchild(),x); //查找左子树//若在左...

weixin_42503762的博客 233
上一篇: Java诊断工具Arthas的简单使用
下一篇: 使用jnotify、commons-io监控文件变化
java_t_t
博客等级 码龄9年 171粉丝 107原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值