golang 实现菜单树的生成方式
来源:脚本之家
时间:2022-12-27 17:57:15 176浏览 收藏
本篇文章向大家介绍《golang 实现菜单树的生成方式》,主要包括生成、菜单树,具有一定的参考价值,需要的朋友可以参考一下。
golang 实现菜单树的生成,包括菜单节点的选中状态、半选中状态,菜单的搜索。
1 该包提供两个方法根接口
1.1 GenerateTree(nodes, selectedNodes []INode) (trees []Tree)
GenerateTree 自定义的结构体实现 INode 接口后调用此方法生成树结构。
1.2 FindRelationNode(nodes, allNodes []INode) (respNodes []INode)
FindRelationNode 在 allTree 中查询 nodes 中节点的所有父子节点 返回 respNodes(包含 nodes , 跟其所有父子节点)
1.3 接口 INode
// ConvertToINodeArray 其他的结构体想要生成菜单树,直接实现这个接口 type INode interface { // GetTitle 获取显示名字 GetTitle() string // GetId获取id GetId() int // GetFatherId 获取父id GetFatherId() int // GetData 获取附加数据 GetData() interface{} // IsRoot 判断当前节点是否是顶层根节点 IsRoot() bool }
2 使用
go get github.com/azhengyongqin/golang-tree-menu
2.1 定义自己的菜单结构体并且实现接口 INode
// 定义我们自己的菜单对象 type SystemMenu struct { Id int `json:"id"` //id FatherId int `json:"father_id"` //上级菜单id Name string `json:"name"` //菜单名 Route string `json:"route"` //页面路径 Icon string `json:"icon"` //图标路径 } func (s SystemMenu) GetTitle() string { return s.Name } func (s SystemMenu) GetId() int { return s.Id } func (s SystemMenu) GetFatherId() int { return s.FatherId } func (s SystemMenu) GetData() interface{} { return s } func (s SystemMenu) IsRoot() bool { // 这里通过FatherId等于0 或者 FatherId等于自身Id表示顶层根节点 return s.FatherId == 0 || s.FatherId == s.Id }
2.2 实现一个将自定义结构体SystemMenu 数组转换成 INode 数组的方法
type SystemMenus []SystemMenu // ConvertToINodeArray 将当前数组转换成父类 INode 接口 数组 func (s SystemMenus) ConvertToINodeArray() (nodes []INode) { for _, v := range s { nodes = append(nodes, v) } return }
3 测试效果
3.1 添加测试数据
// 模拟获取数据库中所有菜单,在其它所有的查询中,也是首先将数据库中所有数据查询出来放到数组中, // 后面的遍历递归,都在这个 allMenu中进行,而不是在数据库中进行递归查询,减小数据库压力。 allMenu := []SystemMenu{ {Id: 1, FatherId: 0, Name: "系统总览", Route: "/systemOverview", Icon: "icon-system"}, {Id: 2, FatherId: 0, Name: "系统配置", Route: "/systemConfig", Icon: "icon-config"}, {Id: 3, FatherId: 1, Name: "资产", Route: "/asset", Icon: "icon-asset"}, {Id: 4, FatherId: 1, Name: "动环", Route: "/pe", Icon: "icon-pe"}, {Id: 5, FatherId: 2, Name: "菜单配置", Route: "/menuConfig", Icon: "icon-menu-config"}, {Id: 6, FatherId: 3, Name: "设备", Route: "/device", Icon: "icon-device"}, {Id: 7, FatherId: 3, Name: "机柜", Route: "/device", Icon: "icon-device"}, }
3.2 生成完全树
// 生成完全树 resp := GenerateTree(SystemMenus.ConvertToINodeArray(allMenu), nil) bytes, _ := json.MarshalIndent(resp, "", "\t") fmt.Println(string(bytes))
[ { "title": "系统总览", "leaf": false, "checked": false, "partial_selected": false, "children": [ { "title": "资产", "leaf": false, "checked": false, "partial_selected": false, "children": [ { "title": "设备", "leaf": true, "checked": false, "partial_selected": false, "children": null }, { "title": "机柜", "leaf": true, "checked": false, "partial_selected": false, "children": null } ] }, { "title": "动环", "leaf": true, "checked": false, "partial_selected": false, "children": null } ] }, { "title": "系统配置", "leaf": false, "checked": false, "partial_selected": false, "children": [ { "title": "菜单配置", "leaf": true, "checked": false, "partial_selected": false, "children": null } ] } ]
3.3 带选中状态和半选中状态的树
// 模拟选中 '资产' 菜单 selectedNode := []SystemMenu{allMenu[2]} resp = GenerateTree(SystemMenus.ConvertToINodeArray(allMenu), SystemMenus.ConvertToINodeArray(selectedNode)) bytes, _ = json.Marshal(resp) fmt.Println(string(pretty.Color(pretty.PrettyOptions(bytes, pretty.DefaultOptions), nil)))
[ { "title": "系统总览", "leaf": false, "checked": false, "partial_selected": true, "children": [ { "title": "资产", "leaf": false, "checked": true, "partial_selected": false, "children": [ { "title": "设备", "leaf": true, "checked": true, "partial_selected": false, "children": null }, { "title": "机柜", "leaf": true, "checked": true, "partial_selected": false, "children": null } ] }, { "title": "动环", "leaf": true, "checked": false, "partial_selected": false, "children": null } ] }, { "title": "系统配置", "leaf": false, "checked": false, "partial_selected": false, "children": [ { "title": "菜单配置", "leaf": true, "checked": false, "partial_selected": false, "children": null } ] } ]
3.4 模拟查询某个节点,然后生成树
// 模拟从数据库中查询出 '设备' device := []SystemMenu{allMenu[5]} // 查询 `设备` 的所有父节点 respNodes := FindRelationNode(SystemMenus.ConvertToINodeArray(device), SystemMenus.ConvertToINodeArray(allMenu)) resp = GenerateTree(respNodes, nil) bytes, _ = json.Marshal(resp) fmt.Println(string(pretty.Color(pretty.PrettyOptions(bytes, pretty.DefaultOptions), nil)))
[ { "title": "系统总览", "leaf": false, "checked": false, "partial_selected": false, "children": [ { "title": "资产", "leaf": false, "checked": false, "partial_selected": false, "children": [ { "title": "设备", "leaf": true, "checked": false, "partial_selected": false, "children": null } ] } ] } ]
源码地址:https://github.com/azhengyongqin/golang-tree-menu
补充:golang实现prim算法,计算最小生成树
1、题目描述
给定一个n个点m条边的无向图,图中可能存在重边和自环,边权可能为负数。
求最小生成树的树边权重之和,如果最小生成树不存在则输出impossible。
给定一张边带权的无向图G=(V, E),其中V表示图中点的集合,E表示图中边的集合,n=|V|,m=|E|。
由V中的全部n个顶点和E中n-1条边构成的无向连通子图被称为G的一棵生成树,其中边的权值之和最小的生成树被称为无向图G的最小生成树。
输入格式
第一行包含两个整数n和m。
接下来m行,每行包含三个整数u,v,w,表示点u和点v之间存在一条权值为w的边。
输出格式
共一行,若存在最小生成树,则输出一个整数,表示最小生成树的树边权重之和,如果最小生成树不存在则输出impossible。
2、数据
数据范围
1≤n≤500,
1≤m≤105,
图中涉及边的边权的绝对值均不超过10000。
输入样例:
4 5
1 2 1
1 3 2
1 4 3
2 3 2
3 4 4
输出样例:
6
数据图
1、初始所有点的距离为正无穷,就是代码中的0x3f3f3f3f等于1061109567
2、以第一个点为最初点,绿色表示选中,进入到最小生成树中
3、以第一个更新其他与之连通的点的距离
4、依次迭代
5、最后的最小生成树
3、朴素prim算法步骤时间复杂度O(n^2)
1、先初始化所有点距离为正无穷
2、迭代n次,依次用到集合的最小点更新剩余点距离
3、将已经确定的点加入到st集合中,st数组为一个bool类型
4、代码实现
/* 该图是稠密图,使用邻接矩阵 */ package main import ( "bufio" "fmt" "os" "strconv" "strings" ) const ( N = 510 INF = 0x3f3f3f3f ) var ( n, m int dist [N]int g [N][N]int st [N]bool ) func readLine(r *bufio.Reader) []int { s, _ := r.ReadString('\n') ss := strings.Fields(s) res := make([]int, len(ss)) for i, v := range ss { res[i], _ = strconv.Atoi(v) } return res } func prim() int { // 初始化距离集合 dist for i := 0; i dist[j]) { t = j } } // 迭代结束,此时的t就是距离最小点 // 情况一:图上的点不连通,不能组成最小生成树 if i > 0 && dist[t] == INF { return INF } // 如果不是第一个点并且最小店的距离是正无穷,则表示图是不连通的 if i > 0 { res += dist[t] } // 如果不是第一个点,这个t就表示当前点到集合某一个点的最小距离 // 用最小距离点更新其他跟 "现阶段形成的生成树" 的最短距离, //注意更新的顺序,自环是不应该被加到最小生成树,所以,为了避免自环加入最小生成树,提前更新res for j := 1; j = b { return b } else { return a } } func main() { r := bufio.NewReader(os.Stdin) input := readLine(r) n, m = input[0], input[1] //fmt.Scanf("%d%d\n", &n, &m) // 初始化距离 for i := 0; i 0 { m-- in := readLine(r) a, b, c := in[0], in[1], in[2] //输入 g[a][b] = min(g[a][b], c) g[b][a] = g[a][b] // 无向图 } t := prim() if t == INF { fmt.Println("impossible") } else { fmt.Println(t) } }
以上为个人经验,希望能给大家一个参考,也希望大家多多支持golang学习网。如有错误或未考虑完全的地方,望不吝赐教。
到这里,我们也就讲完了《golang 实现菜单树的生成方式》的内容了。个人认为,基础知识的学习和巩固,是为了更好的将其运用到项目中,欢迎关注golang学习网公众号,带你了解更多关于golang的知识点!
-
329 收藏
-
416 收藏
-
375 收藏
-
387 收藏
-
460 收藏
-
199 收藏
-
145 收藏
-
168 收藏
-
165 收藏
-
473 收藏
-
377 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 507次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 497次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 484次学习
-
- 粗暴的溪流
- 太细致了,mark,感谢大佬的这篇技术贴,我会继续支持!
- 2023-05-21 11:11:40
-
- 无心的斑马
- 这篇博文太及时了,很详细,赞 👍👍,已加入收藏夹了,关注老哥了!希望老哥能多写Golang相关的文章。
- 2023-04-18 05:05:09
-
- 单身的路灯
- 这篇文章真及时,细节满满,很好,mark,关注师傅了!希望师傅能多写Golang相关的文章。
- 2023-03-19 22:03:25
-
- 生动的小鸭子
- 这篇技术贴真及时,作者大大加油!
- 2023-03-15 18:56:25
-
- 无辜的大船
- 很棒,一直没懂这个问题,但其实工作中常常有遇到...不过今天到这,帮助很大,总算是懂了,感谢作者分享文章!
- 2023-03-06 23:56:49
-
- 腼腆的秀发
- 太给力了,一直没懂这个问题,但其实工作中常常有遇到...不过今天到这,帮助很大,总算是懂了,感谢博主分享文章内容!
- 2023-02-01 05:16:09
-
- 虚心的香水
- 太详细了,已加入收藏夹了,感谢作者大大的这篇技术贴,我会继续支持!
- 2023-01-28 15:38:37
-
- 机智的鸡
- 受益颇多,一直没懂这个问题,但其实工作中常常有遇到...不过今天到这,帮助很大,总算是懂了,感谢博主分享文章内容!
- 2023-01-21 14:17:56
-
- 爱听歌的小甜瓜
- 细节满满,码住,感谢作者的这篇技术文章,我会继续支持!
- 2023-01-11 21:06:55
-
- 虚幻的丝袜
- 这篇文章内容真及时,大佬加油!
- 2023-01-11 08:22:47
-
- 害怕的店员
- 太细致了,码起来,感谢大佬的这篇文章内容,我会继续支持!
- 2023-01-06 21:33:05
-
- 虚心的蜗牛
- 这篇技术文章真是及时雨啊,太细致了,感谢大佬分享,已加入收藏夹了,关注师傅了!希望师傅能多写Golang相关的文章。
- 2023-01-04 17:41:59
-
- 勤奋的小海豚
- 这篇技术贴太及时了,太详细了,感谢大佬分享,码住,关注大佬了!希望大佬能多写Golang相关的文章。
- 2023-01-03 02:26:54
-
- 顺利的服饰
- 很有用,一直没懂这个问题,但其实工作中常常有遇到...不过今天到这,看完之后很有帮助,总算是懂了,感谢博主分享技术文章!
- 2022-12-31 17:47:35