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
golang在GRPC中设置client的超时时间
Apr 27 Golang
go 原生http web 服务跨域restful api的写法介绍
Apr 27 Golang
golang 如何用反射reflect操作结构体
Apr 28 Golang
go语言中fallthrough的用法说明
May 06 Golang
Golang生成Excel文档的方法步骤
Jun 09 Golang
Go 语言下基于Redis分布式锁的实现方式
Jun 28 Golang
Go语言应该什么情况使用指针
Jul 25 Golang
Go 语言中 20 个占位符的整理
Oct 16 Golang
golang操作redis的客户端包有多个比如redigo、go-redis
Apr 14 Golang
Go获取两个时区的时间差
Apr 20 Golang
Go语言怎么使用变长参数函数
Jul 15 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
在任意字符集下正常显示网页的方法一
2007/04/01 PHP
浅析PHP程序设计中的MVC编程思想
2014/07/28 PHP
php数组保存文本与文本反编成数组实例
2014/11/13 PHP
通过php删除xml文档内容的方法
2015/01/23 PHP
php简单中奖算法(实例)
2017/08/15 PHP
jQuery 中关于CSS操作部分使用说明
2007/06/10 Javascript
使用jQuery实现dropdownlist的联动效果(sharepoint 2007)
2011/03/30 Javascript
原生javascript兼容性测试实例
2013/07/01 Javascript
javascript 通用loading动画效果实例代码
2014/01/14 Javascript
实例详解angularjs和ajax的结合使用
2015/10/22 Javascript
JS实现图文并茂的tab选项卡效果示例【附demo源码下载】
2016/09/21 Javascript
js实现图片局部放大效果详解
2019/03/18 Javascript
koa2 用户注册、登录校验与加盐加密的实现方法
2019/07/22 Javascript
Vue开发环境中修改端口号的实现方法
2019/08/15 Javascript
微信小程序向Java后台传输参数的方法实现
2020/12/10 Javascript
[06:20]2015国际邀请赛第三日top10
2015/08/08 DOTA
在Python中使用HTML模版的教程
2015/04/29 Python
在Python中操作文件之read()方法的使用教程
2015/05/24 Python
在Python的Django框架中使用通用视图的方法
2015/07/21 Python
python 中的列表生成式、生成器表达式、模块导入
2019/06/19 Python
Python Django简单实现session登录注销过程详解
2019/08/06 Python
flask 实现token机制的示例代码
2019/11/07 Python
浅谈Tensorflow加载Vgg预训练模型的几个注意事项
2020/05/26 Python
h5页面唤起app如果没安装就跳转下载(iOS和Android)
2020/06/03 HTML / CSS
Parfume Klik丹麦:香水网上商店
2018/07/10 全球购物
Silk Therapeutics官网:清洁、抗衰老护肤品
2020/08/12 全球购物
马来西亚奢侈品牌购物商城:Valiram 247
2020/09/29 全球购物
系统管理员的职责包括那些?管理的对象是什么?
2013/01/18 面试题
本科生个人求职自荐信
2013/09/26 职场文书
运动会通讯稿400字
2014/01/28 职场文书
厨师长岗位职责
2014/03/02 职场文书
内勤主管岗位职责
2014/04/03 职场文书
中学生学雷锋演讲稿
2014/04/26 职场文书
项目投资建议书
2014/05/16 职场文书
公安领导班子四风问题个人整改措施思想汇报
2014/10/09 职场文书
您对思维方式了解多少?
2019/12/09 职场文书