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语言-在mac下brew升级golang
Apr 25 Golang
Golang 实现超大文件读取的两种方法
Apr 27 Golang
解决Golang中goroutine执行速度的问题
May 02 Golang
golang elasticsearch Client的使用详解
May 05 Golang
浅谈golang package中init方法的多处定义及运行顺序问题
May 06 Golang
Go 自定义package包设置与导入操作
May 06 Golang
golang 实现时间戳和时间的转化
May 07 Golang
go goroutine 怎样进行错误处理
Jul 16 Golang
golang中的struct操作
Nov 11 Golang
一文搞懂Golang 时间和日期相关函数
Dec 06 Golang
golang定时器
Apr 14 Golang
深入理解 Golang 的字符串
May 04 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
PHP中开发XML应用程序之基础篇 添加节点 删除节点 查询节点 查询节
2010/07/09 PHP
解析PHP工厂模式的好处
2013/06/18 PHP
php中字符串和正则表达式详解
2014/10/23 PHP
jquery isType() 类型判断代码
2011/02/14 Javascript
Javascript开发之三数组对象实例介绍
2012/11/12 Javascript
toggle一个div显示或隐藏且可扩展成自定义下拉框
2013/09/12 Javascript
玩转方法:call和apply
2014/05/08 Javascript
jquery中show()、hide()和toggle()用法实例
2015/01/15 Javascript
AngualrJS中每次$http请求时的一个遮罩层Directive
2016/01/26 Javascript
详解Backbone.js框架中的模型Model与其集合collection
2016/05/05 Javascript
论Bootstrap3和Foundation5网格系统的异同
2016/05/16 Javascript
Ext JS动态加载JavaScript创建窗体的方法
2016/06/23 Javascript
[原创]jQuery常用的4种加载方式分析
2016/07/25 Javascript
微信小程序开发之数据存储 参数传递 数据缓存
2017/04/13 Javascript
解析Angular 2+ 样式绑定方式
2018/01/15 Javascript
vue1.0和vue2.0的watch监听事件写法详解
2018/09/11 Javascript
Vue使用NPM方式搭建项目
2018/10/25 Javascript
富文本编辑器vue2-editor实现全屏功能
2019/05/26 Javascript
webpack 如何同时输出压缩和未压缩的文件的实现步骤
2020/06/05 Javascript
[04:29]2014DOTA2国际邀请赛 主赛事第三日TOPPLAY
2014/07/21 DOTA
如何解决django配置settings时遇到Could not import settings 'conf.local'
2014/11/18 Python
Python处理CSV与List的转换方法
2018/04/19 Python
python生成九宫格图片
2018/11/19 Python
pycharm 将python文件打包为exe格式的方法
2019/01/16 Python
Python 存储字符串时节省空间的方法
2019/04/23 Python
Python timeit模块的使用实践
2020/01/13 Python
python实现打砖块游戏
2020/02/25 Python
Python PIL库图片灰化处理
2020/04/07 Python
python下对hsv颜色空间进行量化操作
2020/06/04 Python
戴森台湾线上商城:Dyson Taiwan
2018/05/21 全球购物
Hotels.com英国:全球领先的酒店住宿提供商
2019/01/24 全球购物
丧事主持词大全
2014/04/02 职场文书
学生手册评语
2014/05/05 职场文书
简单租房协议书(范本)
2014/10/13 职场文书
入党政审材料范文
2014/12/24 职场文书
魂断蓝桥观后感
2015/06/10 职场文书