菜单树的三种实现形式(递归,for, 队列)

菜单树在软件开发中经常用于展示层级结构的数据,例如网站导航菜单或文件系统。在实际开发中,我们常常需要考虑不同的数据结构和算法来实现这种层级关系的展示。本文将介绍菜单树的三种常见实现方式:递归、for循环和队列,帮助读者更好地理解和选择合适的方法。

 准备

示例数据库

create table menu
(id        int auto_incrementprimary key,name      varchar(100) not null,parent_id int          null
);create index parent_idon menu (parent_id);
 

Mapper

@Mapper
public interface MenuMapper extends BaseMapper<Menu> {@Select("SELECT id, name, parent_id FROM menu WHERE parent_id = #{parentId}")List<Menu> findMenusByParentId(@Param("parentId") Integer parentId);}

Service

public interface MenuService {List<Menu> findMenusByParentId(Integer parentId);
}

 Impl

@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements MenuService {@Autowiredprivate MenuMapper menuMapper;@Overridepublic List<Menu> findMenusByParentId(Integer parentId) {return menuMapper.findMenusByParentId(parentId);}
}

1. 递归实现

@RestController
@RequestMapping("/menus")
public class MenuController {@Autowiredprivate MenuService menuService;// 返回根菜单列表及其子菜单@GetMapping("/tree")public List<Menu> getMenuTree(Integer parentId) {List<Menu> rootMenus = menuService.findMenusByParentId(parentId); // 获取顶级菜单buildMenuTree(rootMenus); // 构建树形结构return rootMenus;}// 递归方法,构建菜单树private void buildMenuTree(List<Menu> menus) {for (Menu menu : menus) {List<Menu> children = menuService.findMenusByParentId(menu.getId());if (!children.isEmpty()) {menu.setChildren(children); // 设置子菜单列表buildMenuTree(children); // 递归构建子树}}}
}

2.For实现

@RestController
@RequestMapping("/treemenus")
public class MenuNotRecursionUseForController {@Resourceprivate MenuService menuService;@GetMapping("/tree")public List<Menu> getMenuTree(Integer parentId) {List<Menu> rootMenus = menuService.findMenusByParentId(parentId); // 获取顶级菜单列表// 创建一个 Map 用于存放每个菜单的 ID 和对应的菜单对象Map<Integer, Menu> menuMap = new HashMap<>();for (Menu menu : rootMenus) {menu.setChildren(new ArrayList<>()); // 初始化子菜单列表menuMap.put(menu.getId(), menu); // 将菜单对象放入 map 中,以便后续快速访问}// 遍历第二层菜单,逐层构建树形结构for (Menu menu : rootMenus) {// 查询当前菜单的所有子菜单(第二层菜单)List<Menu> children = menuService.findMenusByParentId(menu.getId());for (Menu child : children) {// 将第二层菜单添加到父菜单的子菜单列表中Menu parentMenu = menuMap.get(child.getParentId());if (parentMenu != null) {parentMenu.getChildren().add(child);// 查询当前第二层菜单的所有子菜单(第三层菜单)List<Menu> grandchildren = menuService.findMenusByParentId(child.getId());if (child.getChildren() == null) {child.setChildren(new ArrayList<>()); // 初始化第三层子菜单列表}for (Menu grandchild : grandchildren) {// 将第三层菜单添加到当前第二层菜单的子菜单列表中child.getChildren().add(grandchild);}}}}// 返回构建好的根菜单列表return rootMenus;}}

3. 队列实现

@RestController
@RequestMapping("/treemenustwo")
public class MenuNotRecursionUseQueueController {@Autowiredprivate MenuService menuService;@GetMapping("/tree")public List<Menu> getMenuTree(Integer parentId) {List<Menu> rootMenus = menuService.findMenusByParentId(parentId); // 获取顶级菜单列表// 使用队列来进行广度优先搜索Queue<Menu> queue = new LinkedList<>(rootMenus);while (!queue.isEmpty()) {Menu currentMenu = queue.poll(); // 出队当前菜单// 查询当前菜单的所有子菜单List<Menu> children = menuService.findMenusByParentId(currentMenu.getId());// 将子菜单加入当前菜单的 children 列表中currentMenu.setChildren(children);// 将子菜单加入队列,以便后续处理其子菜单queue.addAll(children);}return rootMenus; // 返回构建好的树形结构}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/34237.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

小红书商家采集软件 商家电话批量采集软件

下面是一个关于小红书商家爬虫的程序的示例&#xff1a; import requests from bs4 import BeautifulSoupdef get_seller_data():url https://www.xiaohongshu.com/sellersheaders {User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like…

基于YOLOv8的车辆跟踪与车速计算应用

实现基于YOLOv8的车辆跟踪与车速计算应用涉及以下几个步骤。这里我们假设你已经熟悉Python编程,并且已经安装了所需的库,如YOLOv8、OpenCV等。如果没有,可以先安装这些库: pip install ultralytics opencv-python numpy opencv-contrib-python步骤1:安装和配置YOLOv8 首…

记一下 Stream 流操作

Java Stream流 创建流 Collection.stream() / Collection.parallelStream()&#xff1a;从集合生成流&#xff0c;后者为并行流。 List<String> list new ArrayList<>(); Stream<String> stream list.stream(); //获取一个顺序流 Stream<String> …

single_cell_tutorial 教程

介绍 1、AnnData 不是一个单一的表格,而是一个包含多个表格和矩阵的复杂数据结构,用于处理和存储单细胞基因组数据。 AnnData对象包含以下主要部分: var:基因的元数据(Pandas DataFrame格式),包含每个基因的属性信息。例如每个基因的ID、名称、染色体位置等。可以将其…

软件工程-第4章结构化编码和测试

软件的实现阶段&#xff1a;软件编码&#xff0c;单元测试和综合测试。 软件编码是对软件设计的进一步具体化&#xff0c;其任务是将设计表示变换成用程序设计语言编写的程序。 软件测试是软件质量保证的重要手段&#xff0c;要成功开发出高质量的软件产品&#xff0c;必须认…

如何使用 NFTScan NFT API 在 Sei 网络上开发 Web3 应用

Sei Network 是一个专为交易而设计的 Layer 1 区块链。它建立在 Cosmos SDK 上&#xff0c;使用一种称为 Tendermint BFT 的新型共识机制。不仅专攻 DeFi 领域的加密资产交易&#xff0c;更在游戏、社交媒体和 NFTs 等热门 verticals 构建了多功能区块链生态系统。Sei Network …

Day15—热点搜索词统计

一、要求 根据用户上网的搜索记录对每天的热点搜索词进行统计&#xff0c;以了解用户所关心的热点话题。 要求完成&#xff1a;统计每天搜索数量前3名的搜索词&#xff08;同一天中同一用户多次搜索同一个搜索词视为1次&#xff09;。 二、数据 三、配置scala环境 1.下载sca…

网站制作和推广

在当今数字化时代&#xff0c;拥有一个网站对于企业的发展和推广来说是至关重要的。网站既可以作为一个企业的形象展示&#xff0c;也可以作为一个销售渠道&#xff0c;更可以作为一个品牌传播的平台。在本文中&#xff0c;我们将讨论网站制作和推广的重要性&#xff0c;以及一…

08较成功的降低干扰获得较好的波形

08较成功的降低干扰获得较好的波形 波形数据当前数据调整后的数据后续 结语其他以下是废话 试验&#xff0c;本身就是一个摸索的过程&#xff0c;在上一阶段的试验中&#xff0c;我们优化了采集装置&#xff0c;更换了导电性较好的电极。 目前数据美观程度较之前提升了不少&…

ViT:3 Compact Architecture

大模型技术论文不断&#xff0c;每个月总会新增上千篇。本专栏精选论文重点解读&#xff0c;主题还是围绕着行业实践和工程量产。若在某个环节出现卡点&#xff0c;可以回到大模型必备腔调或者LLM背后的基础模型重新阅读。而最新科技&#xff08;Mamba,xLSTM,KAN&#xff09;则…

动手学深度学习(Pytorch版)代码实践 -卷积神经网络-27含并行连结的网络GoogLeNet

27含并行连结的网络GoogLeNet import torch from torch import nn from torch.nn import functional as F import liliPytorch as lp import matplotlib.pyplot as pltclass Inception(nn.Module):# c1--c4是每条路径的输出通道数def __init__(self, in_channels, c1, c2, c3, …

【kaggle数据集无法下载解决办法】

kaggle数据集无法下载的解决办法 当我们在做机器学习相关问题的时候&#xff0c;需要到kaggle网站上下载数据集&#xff0c;但是很多时候速度很慢或者连接超时等问题&#xff0c;此时解决办法如下&#xff1a; 在本地安装Kaggle API包 打开终端输入如下指令&#xff1a; pip i…

vscode使用内置插件断点调试vue2项目

1、首先项目中要开启source-map 在vue.config.js 文件中 module.exports {configureWebpack: {devtool: process.env.NODE_ENV ! "production" ? "source-map" : ,} }2、项目根目录新建.vscode/launch.js文件 {"configurations": [{"ty…

解析JavaScript中逻辑运算符和||的返回值机制

本文主要内容&#xff1a;了解逻辑运算符 &&&#xff08;逻辑与&#xff09;和 ||&#xff08;逻辑或&#xff09;的返回值。 在JavaScript中&#xff0c;逻辑运算符 &&&#xff08;逻辑与&#xff09;和 ||&#xff08;逻辑或&#xff09;的返回值可能并不总…

GPT-5 一年半后发布?迎接AI技术变革

人工智能的快速发展正在深刻改变我们的世界。作为AI技术的前沿代表&#xff0c;OpenAI的GPT系列一直备受关注。最新消息显示&#xff0c;GPT-5将于一年半后发布&#xff0c;并被期望达到“博士级”的智能水平。GPT-5的到来不仅预示着AI在技术上的飞跃&#xff0c;也意味着它将在…

浏览器提升编译速度小技巧(一)- 防病毒排除

1.引言 在Chrome开发过程中&#xff0c;编译速度是影响开发效率的关键因素之一。编译一个大型项目如Chrome&#xff0c;往往需要处理大量的代码文件和依赖库&#xff0c;这个过程既复杂又耗时。因此&#xff0c;任何能够提升编译速度的技巧&#xff0c;都能显著提高开发效率&a…

Dubbo本地调试解决方案

有三种方式:原文链接 本文尝试使用了原作者推荐的第二种方式&#xff0c;在启动本地的服务时加入全局版本号的参数 -Ddubbo.service.versiontest同时需要修改消费者侧API的版本号。 DubboReference(version "test")private IContentPortraitService contentPortra…

TypeError: Cannot set properties of null (setting ‘innerText‘)?

TypeError: Cannot set properties of null (setting innerText) 解释&#xff1a; 这个错误表明你尝试给一个null值的对象设置innerText属性。在JavaScript中&#xff0c;null表示一个空值或者“没有对象”&#xff0c;因此不能对其进行属性设置操作。 解决方法&#xff1a…

微信小程序的媒体组件

微信小程序中的媒体组件主要包括音频组件 和视频组件 &#xff0c;它们可以帮助开发者在小程序中嵌入和播放多媒体内容。以下是对这两个组件的详细介绍&#xff1a; 音频组件 组件用于在小程序中播放音频文件。它支持多种配置选项和事件处理。 属性 src: 音频资源的 URL 地址。…

Python-题库篇-基础

文章目录 Python-题库篇-基础题目001: 在Python中如何实现单例模式。题目002&#xff1a;不使用中间变量&#xff0c;交换两个变量a和b的值。题目003&#xff1a;写一个删除列表中重复元素的函数&#xff0c;要求去重后元素相对位置保持不变。题目004&#xff1a;假设你使用的是…