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语言-为什么返回值为接口类型,却返回结构体
Apr 24 Golang
Go语言中的UTF-8实现
Apr 26 Golang
Golang 实现超大文件读取的两种方法
Apr 27 Golang
go 原生http web 服务跨域restful api的写法介绍
Apr 27 Golang
基于Go Int转string几种方式性能测试
Apr 28 Golang
Go使用协程交替打印字符
Apr 29 Golang
Go标准容器之Ring的使用说明
May 05 Golang
go语言中fallthrough的用法说明
May 06 Golang
go xorm框架的使用
May 22 Golang
浅谈Go语言多态的实现与interface使用
Jun 16 Golang
Golang表示枚举类型的详细讲解
Sep 04 Golang
实现GO语言对数组切片去重
Apr 20 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笔记之:AOP的应用
2013/04/24 PHP
php Session存储到Redis的方法
2013/11/04 PHP
对于ThinkPHP框架早期版本的一个SQL注入漏洞详细分析
2014/07/04 PHP
Centos 6.5下PHP 5.3安装ffmpeg扩展的步骤详解
2017/03/02 PHP
tp5(thinkPHP5)框架实现多数据库查询的方法
2019/01/10 PHP
Javascript代码混淆综合解决方案-Javascript在线混淆器
2006/12/18 Javascript
jQuery(非HTML5)可编辑表格实现代码
2012/12/11 Javascript
JS中Iframe之间传值及子页面与父页面应用
2013/03/11 Javascript
解析js中获得父窗口链接getParent方法以及各种打开窗口的方法
2013/06/19 Javascript
使用js检测浏览器是否支持html5中的video标签的方法
2014/03/12 Javascript
jQuery圆形统计图开发实例
2015/01/04 Javascript
浅析AngularJS中的生命周期和延迟处理
2015/06/18 Javascript
基于JavaScript实现鼠标悬浮弹出跟随鼠标移动的带箭头的信息层
2016/01/18 Javascript
微信小程序 解析网页内容详解及实例
2017/02/22 Javascript
jQuery使用unlock.js插件实现滑动解锁
2017/04/04 jQuery
微信小程序教程系列之设置标题栏和导航栏(7)
2020/06/29 Javascript
AngularJS学习笔记之表单验证功能实例详解
2017/07/06 Javascript
微信小程序 本地图片按照屏幕尺寸处理
2017/08/04 Javascript
浅谈Webpack 是如何加载模块的
2018/05/24 Javascript
jQuery实现轮播图及其原理详解
2020/04/12 jQuery
vue 项目接口管理的实现
2019/01/17 Javascript
微信小程序新手教程之页面打开数量限制
2019/03/03 Javascript
vue插件mescroll.js实现移动端上拉加载和下拉刷新
2019/03/07 Javascript
微信小程序的引导页实现代码
2020/06/24 Javascript
Python中使用装饰器和元编程实现结构体类实例
2015/01/28 Python
Python MySQLdb模块连接操作mysql数据库实例
2015/04/08 Python
python判断一个集合是否包含了另外一个集合中所有项的方法
2015/06/30 Python
numpy中实现二维数组按照某列、某行排序的方法
2018/04/04 Python
在NumPy中创建空数组/矩阵的方法
2018/06/15 Python
Python基于多线程实现ping扫描功能示例
2018/07/23 Python
python带参数打包exe及调用方式
2019/12/21 Python
在keras里面实现计算f1-score的代码
2020/06/15 Python
Bench加拿大官方网站:英国城市服装品牌
2017/11/03 全球购物
Nike荷兰官方网站:Nike.com (NL)
2018/04/19 全球购物
大学生学习自我评价
2014/01/13 职场文书
企业贷款委托书格式
2014/09/12 职场文书