JAVA算法 List实体创建多叉树,使用递归遍历 实现多级菜单管理

java构建树形菜单(多级菜单) 通过简短的文章,让读者快速掌握树形菜单的原理和制作 阅读详情

项目描述

最近使用SSM做后台系统,已经使用递归的形式动态获取到多级菜单,现写一个多级菜单的管理程序,用于直接遍历出所有菜单,并实现创建菜单以及对菜单的管理与删除。

具体实现效果如下

实现方案

在后台以深度先序递归的方式将数据以JSON的形式遍历出来,在菜单数据表中,主要使用了两个,一个是id,一个是pid,其他数据字段再此不描述。具体流程图

1、先创建多叉树主节点主节点的pid=null,id=0。2、通过查找下一节点节点pid=主节点id值,进行创建子节点

3、遍历使用深度优先遍历的先序搜索进行遍历输出

实现代码

多叉树的节点结构为一个实体MenuTree.class

package com.song.model;


import java.util.ArrayList;
import java.util.List;

import com.alibaba.fastjson.JSON;
import com.song.model.AdminMenu;

public class  MenuTree{
//AdminMenu 为菜单实体
	private AdminMenu nodeEntity;
	private MenuTree parentNode;
	private List<MenuTree> childNodes;  

	public MenuTree(AdminMenu nodeEntity) { 
		this.getParentNode();  
        initChildList();  
	}
	
	
	public MenuTree () {
		initChildList();
	}

    /* 插入一个child节点到当前节点中 */  
	public void addChildNode(MenuTree childNode){
		initChildList();
        this.childNodes.add(childNode);
    }
	
	    
	public MenuTree getParentNode() {
        return parentNode;
    }
 
    public void setParentNode(MenuTree parentNode) {
        this.parentNode = parentNode;
    }
 
    public AdminMenu getNodeEntity() {
        return nodeEntity;
    }
 
    public void setNodeEntity(AdminMenu nodeEntity) {
        this.nodeEntity = nodeEntity;
    }
 
    public List<MenuTree> getChildNodes() {
        return childNodes;
    }
 
    public void setChildNodes(List<MenuTree> childNodes) {
        this.childNodes = childNodes;
    }


}
//返回前端JSON数组
	@ResponseBody
	@RequestMapping(value="/menupower",produces = "application/json;charset=UTF-8")
	public String menupower() {
		List<AdminMenu> menuall = adminmenuservice.superapimenuall();
		List<AdminMenu> menuallapi =new ArrayList<AdminMenu>();
		//创建一个AdminMenu的对象作为多叉树的根的值
		AdminMenu root=new AdminMenu();
		root.setId(0);
		//创建跟节点
		MenuTree roottree =new MenuTree();
		roottree.setNodeEntity(root);
		//开始创建多叉树
		CreateTree(roottree,menuall);
		//遍历多叉树,roottree 为多叉树的根节点,这个函数将根节点遍历给全局变量allmenu对象数组中
		DFStraverse(roottree,menuallapi);
		if(menuallapi.size()==0) {
			return SuperCommon.SuperJson(menuallapi,"超级权限中的菜单管理出错!");
		}
		return JSON.toJSONString(menuallapi);
	}
//创建多叉树
public boolean CreateTree(MenuTree menutree,List<AdminMenu> menuall) {
		if(menutree==null)
			return false;
		//先获取同等级节点
		List<AdminMenu> rootMenu = new ArrayList<AdminMenu>();
		for (AdminMenu res : menuall) {
			if (menutree.getNodeEntity().getId().equals(res.getPid())) {// 父节点是0的,为根节点。
				rootMenu.add(res);
			}
		}
		// 根据Menu类的order排序 ,对同等级节点进行排序
		Collections.sort(rootMenu, order());
		//对rootmenu继续创建节点
		for(AdminMenu res :rootMenu) {
			System.out.println("menutree.getNodeEntity().getId()---------"+menutree.getNodeEntity().getId()+"--------res.getPid()------"+res.getPid());
			if(menutree.getNodeEntity().getId().equals(res.getPid())) {
				System.out.println(JSON.toJSONString(res));
                //使用正则表达式判断获取的id属于第几级菜单,赋予不通的cname值
                if(Pattern.matches("^[1-9]{1}00",Integer.toString(res.getId()))) {
                	res.setCname("&nbsp;"+res.getName());
                }else if(Pattern.matches("^[1-9]{2}0$",Integer.toString(res.getId()))) {
                	res.setCname("&nbsp;&nbsp;&nbsp; ├"+res.getName());
                }else {
                	res.setCname("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |└"+res.getName());
                }
				MenuTree leaf=new MenuTree();
				leaf.setNodeEntity(res);				
				menutree.addChildNode(leaf);
				CreateTree(leaf,menuall);	
			}
		}
		return true;		
	}
/* 遍历一棵树,层次遍历 */ 
	
   
    public void DFStraverse(MenuTree tree,List<AdminMenu> menuapi) {  
        if (tree.getChildNodes() == null || tree.getChildNodes().isEmpty())  
            return;
        int childNumber = tree.getChildNodes().size();  
        for (int i = 0; i < childNumber; i++) {  
        	MenuTree child = tree.getChildNodes().get(i);
        	menuapi.add(child.getNodeEntity());
        	DFStraverse(child,menuapi);  
        }  
    }    
    
    /*
	 * 排序,根据order排序
	 */
	public Comparator<AdminMenu> order() {
		Comparator<AdminMenu> comparator = new Comparator<AdminMenu>() {
			@Override
			public int compare(AdminMenu o1, AdminMenu o2) {
				if (o1.getSort() != o2.getSort()) {
					return o1.getSort() - o2.getSort();
				}
				return 0;
			}
		};
		return comparator;
	}
					

返回前端的数据格式

总结

在采用多叉树遍历所有菜单时,有点笨,使用了两天时间,到现在才明白过来具体具体算法思路,再创建多叉树的时候时由于遇到的一些问题,比如以后创建菜单时会不会发生id冲突,或者创建菜单的级别不同等问题,在创建菜单数据表时对菜单的id与pid做了以下情况,同时菜单只能建立三级,同级只能有九列。

 

直击高频编程考点:树相关知识及经典算法题总结 树相关知识及编程练习总结:背景知识+树的应用举例(Spring中的应用举例+其他框架中的应用举例+实际开发中的应用举例)+相关编程练习(二叉树遍历:包括前序遍历、中序遍历、后序遍历、层序遍历等+二叉树的最大深度+二叉树的最小深度+对称二叉树+二叉树的最近公共祖先+二叉树的直径+二叉树的路径和+二叉搜索树中的插入操作+二叉搜索树中的删除操作+二叉搜索树中的搜索操作+二叉树的层平均值+二叉树的镜像+二叉树的序列化与反序列化+二叉树的右视图+二叉树的最大宽度+前序遍历和中序遍历构造二叉树+平衡二叉树) 阅读详情

相关推荐

程序化广告行业(23/89):深度剖析广告效果评估指标

大家好,我一直希望能和大家一起在技术领域不断探索、共同进步。在之前的文章中,我们了解了程序化广告中腾讯的业务布局和广告效果评估的基础概念,今天让我们进一步深入剖析广告效果评估的各项指标,这对理解程序化广告的运作机制至关重要

yyy173611的博客 4865

Java二叉树遍历:BFS与DFS的本质差异与工程选型

二叉树遍历是算法与工程交汇的基础技术概念,其核心在于理解广度优先搜索(BFS)的时间切片机制与深度优先搜索(DFS)的空间纵深特性。BFS依托队列实现层级扩张,天然支持最近性查找、层序统计与完全二叉树判定;DFS借助栈结构实现路径勘探,适用于路径约束验证、回溯求解与深链遍历。在Java中,ArrayDeque与Stack的选型、递归栈溢出风险、闭包内存泄漏及预分配优化等实践细节,直接决定线上系统的稳定性与性能边界。本文结合订单状态树等真实业务场景,解析二者不可替代的技术价值与落地权衡。

weixin_33727510的博客 373

双目相机立体匹配算法概述(含Python代码)

立体匹配任务是计算机视觉中的一个重要问题,旨在从一对具有相同场景的图像中估计每个像素的视差(disparity)。本文对现有的传统算法和深度学习算法进行了综述,以便于各位选择合适的立体匹配算法用于深度估计或三维建模。

m0_59257547的博客 8293

利用Java8新特性根据id,pid获取树形结构

实体类 @Data @JsonInclude(JsonInclude.Include.NON_NULL) public class SysPermission { private Integer id; private Integer pid; private List<SysPermission> children; } 形成树形结构最关键的是id和pid,其他属性不关键,可以自行定义. 关键代码 // ...上面是获取List<SysPermission&

charismaless的博客 2403

Unidbg补环境实战:复现Shopee风控Native层运行环境

Android App风控已从HTTP层签名校验,演进为深度依赖Native层系统调用与硬件特征的多维验证。其核心原理在于通过JNI桥接Java与Native代码,调用openat、sysconf、getrandom等系统接口读取/proc、/sys、/dev等路径的真实状态,并结合SELinux策略、CPU拓扑、分区哈希等硬性指标构建设备可信画像。这种技术架构显著提升了对抗黑灰产的能力,但也对逆向分析与自动化调用提出更高要求——必须精准模拟底层环境而非仅Hook逻辑。Unidbg补环境正是为此而生:它支持

weixin_30533109的博客 640

【ANSYS Workbench仿真】命令流:压力渗透pressure penetration

对与流体接触的part添加边界压力,使流体压力渗透点的接触应力与流体压力相等,以便得到真实的变形结果,就需要用到“pressure penetration”。 但是在ansys中,只能通过ADPL的形式添加,即在workbench中添加命令流的形式。此文主要介绍了**压力渗透的添加要点**和**命令流使用说明**。

路边小M's Blog 1万+

java id pid,JAVA8 两行代码实现ID-PID转树状结构

核心逻辑通过stream对集合进行分组准备知识:java8的收集器groupingBy 可以根据项目的一个属性的值对流中的项目分组,并将属性值作为结果Map的键,利用这个特性,可以按列表对象中的Pid属性进行分组。Stream收集器groupingBy示意图:StreamGroupingBy示意图第二步,遍历原集合,从Map中取出对应的List存进去。测试用Entity@Datapublic cl...

weixin_32569115的博客 1621

软件破解逆向安全(一)初识内存地址和偏移

工具:CE 内存:数字->存访在电脑中->内存 实例:如何修改植物大战僵尸阳光 内存搜索最核心:过滤数据 先用CE加载植物大战僵尸,如下图 我们可以看到目前我们的阳光数是50,我们尝试在ce里搜索精确数值,4 byte是int整数的表示。 我们发现有很多数据,尝试收集一个阳光变成75再次搜索: 我们发现就一个了,这时我们可以双击Value随便修改阳光的数值了。 这里我们说一下动态和静态地址 动态地址:临时用于存放数据的地址,黑色。特征:重新启动游戏地..

weixin_43781139的博客 2595

Java中树形菜单的实现方式(超全详解!)

就是在实际开发过程中,总会遇到菜单,或则是权限,这个时候就涉及到后端返回数据给前端的时候,不能一个集合把数据一股脑的全部扔给前端,总要把数据整理好,做成像书目录一样的结构返回给前端。就像以下图示一样。

weixin_54542328的博客 5926

CTFshow-pwn入门-前置基础pwn32-pwn34

CTFshow-pwn入门-前置基础pwn32-pwn34

你们de4月天的博客 1132

《深入浅出多模态》(二):多模态任务及数据集介绍

本文为《深入浅出多模态》系列第二章,《多模态任务介绍与背景》主要介绍多模态模型的概念、技术难点、下游任务(Visual Grounding、VQA、image/Video Captioning等)及各类应用方向数据集展开介绍,本专栏适合从事多模态小白及爱好者学习,欢迎大家关注,如有侵权请联系删除!

专注大数据与人工智能技术分享,欢迎私信加群互相学习! 3835

jdk8Stream流操作实现和递归操作实现id与pid 形成树状结构找父子节点

递归处理 @Override public List<PmsProductCategory> listWithChildren() { List<PmsProductCategory> list = categoryMapper.listWithChildren(); List<PmsProductCategory> childMenus = new ArrayList<>(); for (int i =

银魄清辉自夜凝的博客 823

医疗影像分析实战:肺炎X光片分类与分割

医疗影像分析实战:肺炎X光片分类与分割 ,人工智能,计算机视觉,大模型,AI,在医疗领域,医疗影像分析技术凭借其高效、精准的特点,成为疾病诊断与治疗的重要辅助手段。肺炎作为一种常见的呼吸道疾病,严重威胁人类健康,通过 X 光片对肺炎进行诊断是临床常用方法。利用计算机技术实现肺炎 X 光片的自动分类与分割,不仅能减轻医生的工作负担,还能提高诊断的准确性和效率。本文将深入讲解肺炎 X 光片分类与分割的实战过程,结合大量代码示例和关键概念解析,帮助读者掌握相关技术。

不踩坑,不知道坑有多深;不总结,踩过的坑白踩。 3万+

树与森林遍历全解析:从递归迭代到工程实践

在数据结构与算法领域,树形结构是组织层次化数据的核心模型,广泛应用于文件系统、DOM树、组织架构等场景。其访问原理基于系统性的遍历算法,主要包括深度优先(前序、中序、后序)和广度优先(层序)两种策略。从技术价值看,遍历不仅是数据访问的基础,更是实现序列化、依赖分析、规则提取等高级功能的骨架。在工程实践中,递归实现简洁但需警惕栈溢出风险,迭代法则通过显式管理栈或队列提供更稳定的控制。针对多叉树和森林,可通过孩子兄弟表示法转换或循环处理每棵树来适配遍历逻辑。本文结合递归与迭代的对比、栈溢出排查及遍历顺序导致的典

weixin_30621959的博客 337

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

LeetCode 430:扁平化多级双向链表的递归与迭代解法详解

链表是数据结构中的基础,通过节点和指针实现线性序列存储。双向链表在此基础上增加了前驱指针,支持双向遍历。深度优先搜索(DFS)是遍历树或图的重要算法,通过递归或栈实现深度优先访问。在工程实践中,将DFS思想应用于链表操作,可以解决具有嵌套结构的复杂数据扁平化问题。例如,多级双向链表引入了child指针,形成层级结构,其扁平化需求常见于文档大纲、文件目录等场景。本文以链表遍历和链表插入为核心,详细解析如何通过递归与迭代两种方案,将多级链表按深度优先顺序展开为单一双向链表,涵盖指针操作细节、边界处理及调试技巧,

aoe41606的博客 462

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

二叉树数据结构:核心概念、遍历算法与应用实践

二叉树作为基础数据结构,通过节点与指针构成层次关系,每个节点最多包含两个子节点。其核心原理在于平衡存储效率与操作复杂度,既优于线性结构的查询性能,又比多元树更易实现。技术价值体现在O(log n)级别的搜索、插入和删除操作,广泛应用于数据库索引(B+树)、编译器语法分析(AST)和机器学习决策树等场景。深度优先遍历(前序、中序、后序)和广度优先遍历是处理二叉树的基础算法,其中非递归实现和内存管理是工程实践的关键。理解二叉树特性如完全二叉树、平衡二叉树等分类,能有效解决实际开发中的性能优化问题。

weixin_34037515的博客 388

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

C/C++刷题环境搭建与STL实战:从零掌握算法底层实现

算法是计算机科学的核心基础,其本质是通过特定步骤高效解决计算问题。理解算法的时间与空间复杂度,关键在于掌握数据在内存中的组织与访问方式。C/C++语言因其贴近硬件、内存管理透明的特性,成为深入理解算法底层原理的理想工具。通过手动管理内存、操作指针,开发者能直观感知数据结构的扩容、拷贝开销,从而建立对算法性能的深刻认知。在工程实践中,标准模板库(STL)提供了vector、unordered_map等高效容器,配合sort、binary_search等泛型算法,能极大提升开发效率。本文以LeetCode算法训

weixin_30423977的博客 351

蓝桥杯国赛真题解析:树形结构可视化与递归算法实践

树形数据结构是计算机科学中表示层次关系的基础模型,广泛应用于文件系统、组织架构和算法设计。其核心原理在于节点与父子关系的递归定义,通过深度优先遍历可以系统地访问所有节点。掌握树形结构的可视化输出技术,对于调试复杂数据、理解程序状态具有重要价值,尤其在日志分析、目录展示等工程场景中至关重要。本文以一道经典的蓝桥杯国赛真题为例,深入剖析如何通过递归算法实现树形结构的规整打印,涵盖前缀构建、边界处理等关键细节,并探讨其在算法竞赛和实际开发中的应用。

weixin_34082789的博客 366

掌握递归五步法:从LeetCode刷题到工程实践的通用解题框架

递归是计算机科学中一种核心的编程范式,它通过函数自我调用来解决问题,其本质是将复杂问题分解为结构相似的子问题。理解递归的关键在于把握基线条件与递归条件,这有助于构建清晰的程序逻辑并避免栈溢出。在算法设计与工程实践中,递归为处理树形结构、深度优先搜索、回溯与分治等问题提供了优雅的解决方案。例如,在LeetCode刷题和文件目录遍历等场景中,递归思维能显著提升代码的可读性与问题建模能力。本文介绍的“五步法”框架,正是将这一抽象思维具体化为可操作的步骤,旨在帮助开发者系统化地解决递归问题,无论是应对算法面试还是优

weixin_33861800的博客 416

Java树形结构构建与优化实践指南

树形结构作为计算机科学基础数据结构,通过父子节点关系实现层级数据组织,其核心原理在于递归与引用机制。在Java开发中,合理设计树节点类与构建算法能有效支撑权限管理、菜单导航等业务场景。针对性能瓶颈,迭代构建法相比递归更安全,结合Stream API可实现函数式处理。数据库存储方面,邻接表与闭包表模型各有优劣,需根据查询模式选择。典型应用如RBAC系统中,通过树形结构实现角色继承与权限聚合,利用延迟加载和并发控制保证系统稳定性。本文通过CMS菜单重构案例,详解树形结构的工程化实现与常见问题解决方案。

weixin_33858336的博客 360

数据结构C语言版学习指南:从指针链表到排序算法实战

数据结构是计算机科学的核心基础,而C语言正是理解其底层原理的最佳工具。通过结构体与指针,链表、二叉树等抽象结构得以在内存中真实呈现,malloc与free则让内存管理变得直观可见。掌握指针的传值与传址、二级指针的使用场景,是攻克链表操作与递归遍历的关键。从顺序表、栈队列到图与哈希表,C语言版的实现不仅服务于期末复习与考研408,更是面试手撕算法题的底气所在。快速排序、堆排序等经典算法的边界条件与稳定性分析,需要亲手调试才能深刻记忆。无论是植物百科数据管理这类课程设计,还是链表反转、二叉树遍历等高频面试题,C

weixin_34032621的博客 287

递归吃光64GB堆内存?JVM内存模型与递归改非递归实战

在Java后端开发中,递归是处理树形结构、层级菜单等场景的常用手段,但也是JVM内存溢出的高频诱因。理解递归的内存消耗,需要从JVM虚拟机栈与堆的协作机制说起:每一层未返回的调用都会持有栈帧及强引用对象,递归深度越大,堆中滞留对象越多,最终可能同时引发StackOverflowError与OutOfMemoryError。围绕这一原理,工程上衍生出递归改非递归、显式栈模拟调用栈、快速排序非递归化等优化策略,可有效控制内存占用。在大数据量、深层树结构、甚至大Excel解析等场景中,掌握JVM内存模型、堆转储分

weixin_33417488的博客 249

树状结构查询笔试高频题:邻接表+DFS遍历+字典序排序全解析

在算法笔试与真实业务中,树状结构查询是一类高频基础问题:输入往往不是现成树,而是一组父子关系。理解核心并不难——用邻接表把父子关系组织成可检索结构,再通过 DFS/BFS 遍历收集子孙节点,同时用 visited 集合处理重复边和环,最后按字典序排序输出。掌握这套模板,不仅能在在线笔试中稳定拿下类似的 200 分题,也能直接迁移到菜单权限、组织架构、商品分类等场景。无论用 Java、JavaScript 还是 Python,实现细节虽有差异,但算法骨架一致:建表、遍历、去重、排序。以三道常见笔试题为切入点,

weixin_29611239的博客 218

数据结构与算法实战指南:从核心原理到工程选型

数据结构与算法是计算机科学的基础,它研究如何高效地组织和处理数据。其核心原理在于通过合理的数据结构(如数组、链表、树、哈希表)和算法设计(如排序、查找、动态规划),在时间与空间复杂度之间取得平衡,从而提升程序性能。这项技术的价值在于,它是构建高性能、可扩展软件系统的基石,直接决定了系统在应对海量数据和高并发请求时的表现。在实际应用场景中,无论是数据库索引(B+树)、缓存系统(LRU算法)、实时排行榜(堆),还是搜索引擎(Trie树)、任务调度(优先队列),都离不开对数据结构和算法的深刻理解与恰当运用。本文将

weixin_34204722的博客 414

递归从入门到工程实践:调用栈、分治思想与性能优化全解

递归是编程中一种重要的思维模式,本质是问题规模不断缩小的分治思想,底层依赖调用栈逐帧压入与恢复。理解调用栈机制,才能掌握递归的终止条件与递推关系,避免栈溢出和死循环。递归虽简洁,但也存在重复计算和性能瓶颈,可借助记忆化、尾递归或迭代改写来优化。树形结构遍历、嵌套JSON处理、图搜索等场景都离不开递归。本文系统梳理递归原理、设计方法论、典型优化策略及真实工程中的避坑技巧,帮助开发者写出高鲁棒性的递归代码。

weixin_42591908的博客 185

基于Spring Boot的面试试题管理系统:设计、实现与毕设全攻略

在Java后端开发中,构建一套完整的业务管理系统需要统筹数据模型、接口权限、前后端交互等核心环节。Spring Boot作为主流框架,配合MyBatis-Plus持久层和JWT无状态鉴权,能高效搭建结构清晰的Web应用。从企业招聘、在线教育到培训测评,题库类系统都是真实落地的高频场景。开发此类系统的关键在于数据库设计的完整性——用户、试题、试卷、考试记录与错题本等实体需要形成业务闭环;同时,自动组卷的难度控制、随机抽题防重复等算法逻辑也直接体现系统深度。本文以面试试题管理系统为例,详细拆解从选题规划、技术选

weixin_32667955的博客 277
上一篇: Java 多叉树的实现,完成树的初始化和遍历
下一篇: 前端小技巧:js 动态创建table标签下的tr标签
concealed0
博客等级 码龄9年 63粉丝 45原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值