菜单展示的递归与非递归形式实现 (go语言版)
1.递归形式实现
节点分为三种:根节点、中间节点、叶子节点,其中一个树可以有多个根节点
结构体
type MenuTree struct {
Name string `json:"name"`
ID string `json:"id"`
Description string `json:"description"`
ParentID string `json:"parentId"`
HeaderGroupID string `json:"headerGroupId"`//用于记录该节点所属的根节点,可以便于查找指定根节点的所有child
Children []*MenuTree `json:"childrens"`
}
获取指定节点的叶子节点
func GetNodeLeafIds(menuTree *MenuTree, nodeID string) []string {
node := findNode(menuTree, nodeID)
if node == nil {
return nil
}
ids := make([]string, 0)
getLeafIds(node, &ids)
return ids
}
查找某一中间节点是否有包含指定节点
func findNode(menuTree *MenuTree, nodeID string) *MenuTree {
if menuTree.ID == nodeID {
return menuTree
}
for _, child := range menuTree.Children {
if child.ID == nodeID {
return child
}
findNode(child, nodeID)
}
return nil
}
获取指定节点的所有叶子节点
func getLeafIds(node *MenuTree, lefts *[]string) {
for _, child := range node.Children {
if child.Children == nil || len(child.Children) == 0 {
*lefts = append(*lefts, child.ID)
}
getLeafIds(child, lefts)
}
}
获取所有根节点
func getRoots(datas []*MenuTree) []*MenuTree {
roots := []*MenuTree{}
for _, data := range datas {
if data.ParentID == "" {//父节点为空的为根节点
root := MenuTree{
Name : data.Name,
ID : data.ID,
Description : data.Description,
ParentID : data.ParentID,
HeaderGroupID: data.HeaderGroupID,
Children : []*MenuTree{},
}
roots = append(roots, &root)
}
}
return roots
}
给指定的根节点构建树,datas为所有菜单的数据,root为指定根节点
func buildChild(datas []*MenuTree, root *MenuTree) *MenuTree {
for _, data := range datas {
if data.ParentID == root.ID {
root.Children = append(root.Children, buildChild(datas, data))
}
}
return root
}
构建所有根节点的树
func BuildTree(allMenus []*MenuTree) []*MenuTree {
roots := getRoots(allMenus)
for _, root := range roots {
buildChild(allMenus, root)
}
return roots
}
2.非递归形式实现
func buildMenuTree(allMenus []*MenuTree ) map[string]*MenuTree {
temp := map[string]*MenuTree{}
result := map[string]*MenuTree{}
for _, menu := range allMenus {
temp[menu.ID] = &menu
}
for _, node := range temp {
if temp[node.ParentID] == nil {
result[node.ID] = node
} else {
temp[node.ParentID].Children = append(temp[node.ParentID].Children, node)
}
}
return result
}
如果觉得写得不好,欢迎指出;如果觉得写得不错,欢迎大佬赞赏。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· .NET Core 中如何实现缓存的预热?
· 三行代码完成国际化适配,妙~啊~
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?