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 相关文章推荐
golang判断key是否在map中的代码
Apr 24 Golang
golang中实现给gif、png、jpeg图片添加文字水印
Apr 26 Golang
golang 实现菜单树的生成方式
Apr 28 Golang
golang 如何用反射reflect操作结构体
Apr 28 Golang
go语言基础 seek光标位置os包的使用
May 09 Golang
go语言中http超时引发的事故解决
Jun 02 Golang
再次探讨go实现无限 buffer 的 channel方法
Jun 13 Golang
Go语言应该什么情况使用指针
Jul 25 Golang
Golang表示枚举类型的详细讲解
Sep 04 Golang
Golang 并发编程 SingleFlight模式
Apr 26 Golang
Golang入门之计时器
May 04 Golang
Go 内联优化让程序员爱不释手
Jun 21 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自定义的格式化时间示例代码
2013/12/05 PHP
php绘图之生成饼状图的方法
2015/01/24 PHP
thinkphp3.x中变量的获取和过滤方法详解
2016/05/20 PHP
基于JQuery框架的AJAX实例代码
2009/11/03 Javascript
javascript 广告后加载,加载完页面再加载广告
2010/11/25 Javascript
javascript错误的认识不用关心内存管理
2012/12/15 Javascript
js随机颜色代码的多种实现方式
2013/04/23 Javascript
JavaScript中的console.log()函数详细介绍
2014/12/29 Javascript
利用Javascript裁剪图片并存储的简单实现
2017/03/13 Javascript
layui select动态添加option的实例
2018/03/07 Javascript
Layer弹出层动态获取数据的方法
2018/08/20 Javascript
Vue 组件参数校验与非props特性的方法
2019/02/12 Javascript
基于JS+HTML实现弹窗提示是否确认提交功能
2020/06/17 Javascript
基于vue项目设置resolves.alias: '@'路径并适配webstorm
2020/12/02 Vue.js
[41:56]Spirit vs Liquid Supermajor小组赛A组 BO3 第一场 6.2
2018/06/03 DOTA
Python中apply函数的用法实例教程
2014/07/31 Python
Python中字符串格式化str.format的详细介绍
2017/02/17 Python
python中正则表达式的使用方法
2018/02/25 Python
解决Pycharm无法import自己安装的第三方module问题
2018/05/18 Python
Cython编译python为so 代码加密示例
2019/12/23 Python
python使用配置文件过程详解
2019/12/28 Python
Python数据结构dict常用操作代码实例
2020/03/12 Python
PyCharm License Activation激活码失效问题的解决方法(图文详解)
2020/03/12 Python
Keds官方网站:购买帆布运动鞋和经典皮鞋
2016/11/12 全球购物
意大利时尚奢侈品店:D’Aniello Boutique
2021/01/19 全球购物
2014年会演讲稿范文
2014/01/06 职场文书
社团招新策划书
2014/02/04 职场文书
《云房子》教学反思
2014/04/20 职场文书
国旗下的讲话演讲稿
2014/05/08 职场文书
妇女干部培训方案
2014/05/12 职场文书
综治工作心得体会
2014/09/11 职场文书
2014年消防工作总结
2014/11/21 职场文书
拾金不昧感谢信范文
2015/01/21 职场文书
小学英语教师研修感悟
2015/11/18 职场文书
中小学教师继续教育心得体会
2016/01/19 职场文书
springboot新建项目pom.xml文件第一行报错的解决
2022/01/18 Java/Android