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
Go语言-为什么返回值为接口类型,却返回结构体
Apr 24 Golang
Go缓冲channel和非缓冲channel的区别说明
Apr 25 Golang
Golang 正则匹配效率详解
Apr 25 Golang
golang 如何用反射reflect操作结构体
Apr 28 Golang
golang slice元素去重操作
Apr 30 Golang
Go语言应该什么情况使用指针
Jul 25 Golang
一文搞懂Golang 时间和日期相关函数
Dec 06 Golang
golang实现浏览器导出excel文件功能
Mar 25 Golang
如何解决goland,idea全局搜索快捷键失效问题
Apr 03 Golang
golang三种设计模式之简单工厂、方法工厂和抽象工厂
Apr 10 Golang
Golang数据类型和相互转换
Apr 12 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下载xls文件(自己动手写的)
2014/04/18 PHP
PHP实现根据设备类型自动跳转相应页面的方法
2014/07/24 PHP
取得单条网站评论以数组形式进行输出
2014/07/28 PHP
PHP中__FILE__、dirname与basename用法实例分析
2014/12/01 PHP
PHP7移除的扩展和SAPI
2021/03/09 PHP
Javascript实现仿WebQQ界面的“浮云”兼容 IE7以上版本及FF
2011/04/27 Javascript
jQuery Deferred和Promise创建响应式应用程序详细介绍
2013/03/05 Javascript
Jquery倒数计时按钮setTimeout的实例代码
2013/07/04 Javascript
生成二维码方法汇总
2014/12/26 Javascript
Javascript函数式编程语言
2015/10/11 Javascript
AngularJS 入门教程之事件处理器详解
2016/08/19 Javascript
理解javascript中的Function.prototype.bind的方法
2017/02/03 Javascript
JavaScript中concat复制数组方法浅析
2019/01/20 Javascript
基于layui框架响应式布局的一些使用详解
2019/09/16 Javascript
详解element-ui中表单验证的三种方式
2019/09/18 Javascript
用vite搭建vue3应用的实现方法
2021/02/22 Vue.js
[02:17]《辉夜杯》TRG战队巡礼
2015/10/26 DOTA
Python多层嵌套list的递归处理方法(推荐)
2016/06/08 Python
神经网络(BP)算法Python实现及应用
2018/04/16 Python
python设置环境变量的作用整理
2020/02/17 Python
前端实现打印图像功能
2019/08/27 HTML / CSS
韩国CJ食品专卖网:CJonmart
2016/09/11 全球购物
美国网上书店:Barnes & Noble
2018/08/15 全球购物
英国泽西岛植物:Jersey Plants Direct
2019/08/07 全球购物
密封类可以有虚函数吗
2014/08/11 面试题
历史学专业毕业生求职信
2013/09/27 职场文书
物流管理专业毕业生求职信
2014/03/23 职场文书
标准离婚协议书范文下载
2014/11/30 职场文书
老乡聚会通知
2015/04/23 职场文书
安全第一课观后感
2015/06/18 职场文书
2016领导干部廉洁从政心得体会
2016/01/19 职场文书
JS监听Esc 键触发事键
2021/04/14 Javascript
pytorch 权重weight 与 梯度grad 可视化操作
2021/06/05 Python
Redis集群新增、删除节点以及动态增加内存的方法
2021/09/04 Redis
Nginx的gzip相关介绍
2022/05/11 Servers
使用Postman测试需要授权的接口问题
2022/06/21 Java/Android