golang通过递归遍历生成树状结构的操作


Posted in Golang onApril 28, 2021

业务场景:

一个机构查询科室信息的时候,希望返回树状结构的嵌套格式;

解决办法:

通过递归和指针,嵌套成对应的结构体;

借鉴了前人的代码,但是最后递归的指针调用自己也是调试了半天才出来,这里献上完整的示例代码.

package main
import (
	"fmt"
	"encoding/json"
)
 
type dept struct {
	DeptId string `json:"deptId"`
	FrameDeptStr string `json:"frameDeptStr"`
	Child []*dept `json:"child"`
}
func main() {
	depts := make([]dept,0)
	var a dept
	a.DeptId = "1"
	a.FrameDeptStr = ""
	depts = append(depts,a)
	a.DeptId="3"
	a.FrameDeptStr = "1"
	depts = append(depts,a)
	a.DeptId="4"
	a.FrameDeptStr = "1"
	depts = append(depts,a)
	a.DeptId="5"
	a.FrameDeptStr = "13"
	depts = append(depts,a)
	a.DeptId="6"
	a.FrameDeptStr = "13"
	depts = append(depts,a)
	fmt.Println(depts)
 
	deptRoots := make([]dept,0)
	for _,v := range depts{
		if v.FrameDeptStr == ""{
			deptRoots= append(deptRoots,v)
		}
	}
 
	pdepts := make([]*dept,0)
	for i,_ := range depts{
		var a *dept
		a = &depts[i]
		pdepts = append(pdepts,a)
	}
	//获取了根上的科室
	fmt.Println("根上的科室有:",deptRoots)
 
 
	var node *dept
	node = &depts[0]
	makeTree(pdepts,node)
	fmt.Println("the result we got is",pdepts)
	data, _ := json.Marshal(node)
	fmt.Printf("%s", data)

}
 
func has(v1 dept,vs []*dept) bool  {
	var has bool
	has = false
	for _,v2 := range vs {
		v3 := *v2
		if v1.FrameDeptStr+v1.DeptId == v3.FrameDeptStr{
			has = true
			break
		}
	}
	return has
}
 
func makeTree(vs []*dept,node *dept) {
	fmt.Println("the node value in maketree is:",*node)
	childs := findChild(node,vs)
	fmt.Println(" the child we got is :",childs)
	for _,child := range childs{
		fmt.Println("in the childs's for loop, the child's address  here is:",&child)
		node.Child = append(node.Child,child)
		fmt.Println("in the child's for loop, after append the child is:",child)
		if has(*child,vs) {
			fmt.Println("i am in if has")
			fmt.Println("the child in if has is:",*child)
			fmt.Println("the child in if has 's address is:",child)
			makeTree(vs,child)
		}
	}
}
 
func findChild(v *dept,vs []*dept)(ret []*dept)  {
	for _,v2 := range vs{
		if v.FrameDeptStr+v.DeptId == v2.FrameDeptStr{
			ret= append(ret,v2)
		}
	}
	return
}

代码备注:

通过frame_dept_str来确定科室之间的关系的, (a.frame_dept_str= a's parent's frame_dept_str + a's parent's dept_id).

补充:golang的树结构三种遍历方式

看代码吧~

package main
import "log"
type node struct {
	Item  string
	Left  *node
	Right *node
}
type bst struct {
	root *node
}
/*
        m
     k     l
  h    i     j
a  b  c  d  e  f
//先序遍历(根左右):m k h a b i c d l j e f
//中序遍历(左根右):a h b k c i d m l e j f
//后序遍历(左右根):a b h c d i k e f j l m
*/
func (tree *bst) buildTree() {
	m := &node{Item: "m"}
	tree.root = m
	k := &node{Item: "k"}
	l := &node{Item: "l"}
	m.Left = k
	m.Right = l
	h := &node{Item: "h"}
	i := &node{Item: "i"}
	k.Left = h
	k.Right = i
	a := &node{Item: "a"}
	b := &node{Item: "b"}
	h.Left = a
	h.Right = b
	c := &node{Item: "c"}
	d := &node{Item: "d"}
	i.Left = c
	i.Right = d
	j := &node{Item: "j"}
	l.Right = j
	e := &node{Item: "e"}
	f := &node{Item: "f"}
	j.Left = e
	j.Right = f
}
//先序遍历
func (tree *bst) inOrder() {
	var inner func(n *node)
	inner = func(n *node) {
		if n == nil {
			return
		}
		log.Println(n.Item)
		inner(n.Left)
		inner(n.Right)
	}
	inner(tree.root)
}
//中序
func (tree *bst) midOrder() {
	var inner func(n *node)
	inner = func(n *node) {
		if n == nil {
			return
		}
		inner(n.Left)
		log.Println(n.Item)
		inner(n.Right)
	}
	inner(tree.root)
}
//后序
func (tree *bst) lastOrder() {
	var inner func(n *node)
	inner = func(n *node) {
		if n == nil {
			return
		}
		inner(n.Left)
		inner(n.Right)
		log.Println(n.Item)
	}
	inner(tree.root)
}
func main() {
	tree := &bst{}
	tree.buildTree()
	// tree.inOrder()
	tree.lastOrder()
}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持三水点靠木。如有错误或未考虑完全的地方,望不吝赐教。

Golang 相关文章推荐
一文读懂go中semaphore(信号量)源码
Apr 03 Golang
go语言map与string的相互转换的实现
Apr 07 Golang
golang判断key是否在map中的代码
Apr 24 Golang
goland 清除所有的默认设置操作
Apr 28 Golang
golang 如何通过反射创建新对象
Apr 28 Golang
golang 实现Location跳转方式
May 02 Golang
Goland使用Go Modules创建/管理项目的操作
May 06 Golang
go语言中http超时引发的事故解决
Jun 02 Golang
Go语言空白表示符_的实例用法
Jul 04 Golang
K8s部署发布Golang应用程序的实现方法
Jul 16 Golang
golang中的struct操作
Nov 11 Golang
Python测试框架pytest核心库pluggy详解
Aug 05 Golang
goland 恢复已更改文件的操作
goland 清除所有的默认设置操作
go 原生http web 服务跨域restful api的写法介绍
Apr 27 #Golang
解决Golang中ResponseWriter的一个坑
Apr 27 #Golang
golang在GRPC中设置client的超时时间
golang http使用踩过的坑与填坑指南
Apr 27 #Golang
Golang 实现超大文件读取的两种方法
Apr 27 #Golang
You might like
PHPMailer 中文使用说明小结
2010/01/22 PHP
关于PHP的相似度计算函数:levenshtein的使用介绍
2013/04/15 PHP
PHP代码优化技巧小结
2015/09/29 PHP
thinkPHP删除前弹出确认框的简单实现方法
2016/05/16 PHP
PHP使用Curl实现模拟登录及抓取数据功能示例
2018/04/27 PHP
两个DIV等高的JS的实现代码
2007/12/23 Javascript
不安全的常用的js写法
2009/09/15 Javascript
Javascript学习笔记二 之 变量
2010/12/15 Javascript
基于jquery的拖动布局插件
2011/11/25 Javascript
jquery重新播放css动画所遇问题解决
2013/08/21 Javascript
JavaScript实现复制内容到粘贴板代码
2016/03/31 Javascript
Angular2实现组件交互的方法分析
2017/12/19 Javascript
Vue中的v-for循环key属性注意事项小结
2018/08/12 Javascript
koa源码中promise的解读
2018/11/13 Javascript
微信上传视频文件提示(推荐)
2018/11/22 Javascript
Javascript迭代、递推、穷举、递归常用算法实例讲解
2019/02/01 Javascript
vue的for循环使用方法
2019/02/12 Javascript
解决layui表格内文本超出隐藏的问题
2019/09/12 Javascript
vue实现购物车结算功能
2020/06/18 Javascript
[03:39]2015国际邀请赛主赛事首日精彩回顾
2015/08/05 DOTA
[03:37]2016完美“圣”典 风云人物:Mikasa专访
2016/12/07 DOTA
[58:15]2018DOTA2亚洲邀请赛 4.1 小组赛 A组 NB vs Liquid
2018/04/02 DOTA
python实现给微信指定好友定时发送消息
2019/04/29 Python
pandas的qcut()方法详解
2019/07/06 Python
使用python实现男神女神颜值打分系统(推荐)
2019/10/31 Python
pytorch三层全连接层实现手写字母识别方式
2020/01/14 Python
Python 测试框架unittest和pytest的优劣
2020/09/26 Python
AmazeUI底部导航栏与分享按钮的示例代码
2020/08/18 HTML / CSS
村干部群众路线教育活动对照检查材料
2014/10/01 职场文书
教代会开幕词
2015/01/28 职场文书
《生物入侵者》教学反思
2016/02/16 职场文书
描述鲁迅的名言整理,一生受用
2019/08/08 职场文书
导游词之长城八达岭
2019/09/24 职场文书
导游词之山东八仙过海景区
2019/11/11 职场文书
Ajax 的初步实现(使用vscode+node.js+express框架)
2021/06/18 Javascript
为什么MySQL 删除表数据 磁盘空间还一直被占用
2021/10/16 MySQL