Golang非递归构建菜单树(O(n)时间复杂度,任意深度的递归树都能构造,适用于深层、大量数据的树结构构造)

2023-11-04

刚刚学习到Go的接口部分,希望对之前的基础部分(struct、slice、map)做一个简单的总结!
希望各位Go语言方面的大佬给一点意见,非常感谢!!!

编写过程中存在的一些疑惑:

  • TreeNode结构中定义的Child()和SetChild()方法都是返回的接口本身,但是在结构体定义以及实现的时候感觉用着有点别扭,没有Java那么顺畅(可能是Go还不熟悉)。。。
package main

import (
	"fmt"
	"strconv"
)

// TreeNode 节点接口
type TreeNode interface {
	// Id 节点ID
	Id() int
	// Pid 父节点ID
	Pid() int
	// Name 节点名称
	Name() string
	// Child 获取子节点切片
	Child() *[]*TreeNode
	// String 节点打印方法
	String() string
}

// BuildTree 构建树结构
func BuildTree(nodes []TreeNode, root int) []TreeNode {
	collect := make(map[int]*TreeNode, len(nodes))
	for idx, elem := range nodes {
		collect[elem.Id()] = &nodes[idx]
	}
	var result []TreeNode
	for key, val := range collect {
		if (*val).Pid() == root {
			result = append(result, *val)
		} else {
			*(*collect[(*val).Pid()]).Child() = append(*(*collect[(*val).Pid()]).Child(), collect[key])
		}
	}
	return result
}

// Menu 菜单,实现节点接口以此构建菜单树
type Menu struct {
	id    int         //节点ID
	pid   int         //父节点ID
	name  string      //节点名称
	child []*TreeNode //子节点
}

func (menu *Menu) String() string {
	ss := "{\"id\": " + strconv.Itoa(menu.id) + ", \"pid\": " + strconv.Itoa(menu.pid) + ", \"name\": \"" + menu.name + "\", \"child\": ["
	for idx, elem := range menu.child {
		if idx == len(menu.child)-1 {
			ss += (*elem).String()
		} else {
			ss += (*elem).String() + ","
		}
	}
	ss += "]}"
	return ss
}

func (menu *Menu) Id() int {
	return menu.id
}

func (menu *Menu) Pid() int {
	return menu.pid
}

func (menu *Menu) Name() string {
	return menu.name
}

// Child 获取当前对象的子节点对象切片,一定要用指针接收器,因为非指针接收器不能修改当前对象
func (menu *Menu) Child() *[]*TreeNode {
	return &menu.child
}

func main() {
	var list = []TreeNode{
		&Menu{1, 0, "一级节点01", []*TreeNode{}},
		&Menu{2, 0, "一级节点02", []*TreeNode{}},
		&Menu{3, 0, "一级节点03", []*TreeNode{}},
		&Menu{11, 1, "二级节点01", []*TreeNode{}},
		&Menu{14, 1, "二级节点04", []*TreeNode{}},
		&Menu{15, 1, "二级节点05", []*TreeNode{}},
		&Menu{12, 2, "二级节点02", []*TreeNode{}},
		&Menu{16, 2, "二级节点06", []*TreeNode{}},
		&Menu{13, 3, "二级节点03", []*TreeNode{}},
		&Menu{21, 11, "三级节点01", []*TreeNode{}},
		&Menu{22, 11, "三级节点02", []*TreeNode{}},
		&Menu{23, 14, "三级节点03", []*TreeNode{}},
		&Menu{24, 15, "三级节点04", []*TreeNode{}},
		&Menu{25, 16, "三级节点05", []*TreeNode{}},
		&Menu{26, 12, "三级节点06", []*TreeNode{}},
		&Menu{27, 12, "三级节点07", []*TreeNode{}},
	}
	tree := BuildTree(list, 0)
	for _, node := range tree {
		fmt.Printf("%v\n", node.String())
	}
}

执行结果(Json格式化的时候请使用正则将\n换行符去除,这个输出自动加了换行符,目前不晓得原理。。。):
在这里插入图片描述

使用Json格式化后的结果:

{
  "id": 1,
  "pid": 0,
  "name": "一级节点01",
  "child": [
    {
      "id": 14,
      "pid": 1,
      "name": "二级节点04",
      "child": [
        {
          "id": 23,
          "pid": 14,
          "name": "三级节点03",
          "child": []
        }
      ]
    },
    {
      "id": 15,
      "pid": 1,
      "name": "二级节点05",
      "child": [
        {
          "id": 24,
          "pid": 15,
          "name": "三级节点04",
          "child": []
        }
      ]
    },
    {
      "id": 11,
      "pid": 1,
      "name": "二级节点01",
      "child": [
        {
          "id": 21,
          "pid": 11,
          "name": "三级节点01",
          "child": []
        },
        {
          "id": 22,
          "pid": 11,
          "name": "三级节点02",
          "child": []
        }
      ]
    }
  ]
}

{
  "id": 2,
  "pid": 0,
  "name": "一级节点02",
  "child": [
    {
      "id": 12,
      "pid": 2,
      "name": "二级节点02",
      "child": [
        {
          "id": 26,
          "pid": 12,
          "name": "三级节点06",
          "child": []
        },
        {
          "id": 27,
          "pid": 12,
          "name": "三级节点07",
          "child": []
        }
      ]
    },
    {
      "id": 16,
      "pid": 2,
      "name": "二级节点06",
      "child": [
        {
          "id": 25,
          "pid": 16,
          "name": "三级节点05",
          "child": []
        }
      ]
    }
  ]
}

{
  "id": 3,
  "pid": 0,
  "name": "一级节点03",
  "child": [
    {
      "id": 13,
      "pid": 3,
      "name": "二级节点03",
      "child": []
    }
  ]
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Golang非递归构建菜单树(O(n)时间复杂度,任意深度的递归树都能构造,适用于深层、大量数据的树结构构造) 的相关文章

随机推荐

  • 数据中台数据分析过程梳理

    在当今社会中 随着企业的快速发展 相关业务系统的建设也会越来越多 新的业务模式 新的IT架构 多云环境的出现等等 而一些问题就逐渐暴露了出来 企业之间的IT无法做到互通 新模式生产数据与旧数据无法互通 企业IT架构错综复杂 底层数据互通更加
  • java使用opencv库二值化图片

    应用场景 截取监控视频图片保存到本地后用作后期监控视频角度调整参考 使用二值化后的图片并进行透明度降低进行监控矫正 package img import java awt Color import java awt image Buffer
  • delphi XE5如何把其它程序而不是本软件在通知区域的图标隐藏?不是关闭进程。请举个详细例子,比如Shell_NotifyIcon...

    Delphi XE5可以使用API函数Shell NotifyIcon来实现隐藏其它程序的图标 具体代码例子如下 procedure HideIcon APid Cardinal var noteIconData TNOTIFYICONDA
  • 关于 hostapd

    关于 hostapd 主页 http w1 fi hostapd hostapd是一个IEEE 802 11的AP和IEEE 802 1X WPA WPA2 EAP RADIUS验证器 此页面用于怎么在linux系统下使用它 其他操作系统请
  • 金融贷款行业实时高精准获客 ——三网运营商大数据

    都说生产是第一因素 但对于任何企业来说 客户来源才是第一因素 在大多数行业 获得客户的困难已经成为行业的挑战 如今 许多行业和企业获得客户的主要来源是在线促销和客户获取 现在几乎每个人都有一部手机 运营商可以根据移动客户的访问行为 通信行为
  • 排查java.net.MalformedURLException: Local host name unknown: java.net.UnknownHostException:***

    首先排查 vi etc sysconfig network 没有就加上 HOSTNAME 你的主机名 XXXX 如果有 接着排查 vi etc hosts 没有就加上 127 0 0 1 localhost localdomain loca
  • 2021年全球与中国高速分散机行业市场规模及发展前景分析

    2021年全球与中国高速分散机行业市场规模及发展前景分析 本报告研究全球与中国市场高速分散机的发展现状及未来发展趋势 分别从生产和消费的角度分析高速分散机的主要生产地区 主要消费地区以及主要的生产商 重点分析全球与中国市场的主要厂商产品特点
  • 论文阅读:DeepFake-Adapter: Dual-Level Adapter for DeepFake Detection(Deepfake模型快速调参)

    一 论文信息 论文名称 DeepFake Adapter Dual Level Adapter for DeepFake Detection 作者团队 项目主页 https github com rshaojimmy DeepFake Ad
  • python爬取 百姓网部分数据 + 存入MongoDB数据库详细案例

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 目录 前言 一 实施步骤 二 目标网站 先分析目标网站 三 获取数据 1 引入库 2 请求数据 2 1 获取第一层链接 3 抓取数据 3 1 分析页面 3 2 抓取数据 四
  • 图像可变游程之混乱代码

    图像可变游程之混乱代码 图像可变游程之混乱编码 可变游程编码 VLC 混乱编码 参考代码 图像可变游程之混乱编码 这里 对我的自画像代码作一个简要解释 自画像代码实际上是一个解码器 包括两个部分 图像的可变游程编码 varied lengt
  • ValueError: check_hostname requires server_hostnameWARNING: You are using pip version 21.1.3

    ValueError check hostname requires server hostname WARNING You are using pip version 21 1 3 however version 22 2 2 is av
  • LCD1602芯片的使用——简单易懂

    题目 想在LCD1602上显示两行如下字样 huaianxinxi wantin 想完成上面的显示必须掌握LCD1602芯片的基本知识 将在程序下面附上LCD1602芯片的基本知识 供大家参考 我实现的比较简单 没有什么花哨的显示 大家首先
  • js 聚合函数

    在JavaScript中 聚合函数是一种用于处理数据集合的函数 它们接收一个数据集合作为输入 并返回一个单一的值作为输出 聚合函数通常用于对数据进行统计 计算总和 平均值 最大值 最小值等操作 下面是一些常见的聚合函数的概念 sum 求和
  • Vscode搭建轻量级Matlab开发环境

    一 使用Vscode编写m文件的优势与不足 Matlab的启动速度很慢 为追求效率与编写体验 对于一些简单的m文件编写 我们可以选择在Vscode中进行编写和运行 Vscode插件丰富 配置好Matlab环境后 可以实现以下功能 代码高亮
  • MATLAB及Simulink----基本知识简介

    目前 MATLAB已成为国际上最为流行的科学计算与工程计算软件工具之一 如今的MATLAB已经不仅仅是矩阵运算或数值计算的软件 它已经发展成为一种具有广泛应用前景 全新的计算机高级编程语言 可以说它是 第四代 计算机语言 自20世纪90年代
  • Sqli-labs之Less-37

    Less 37 POST型 绕过 MYSQL real escape string 本关与 34 关是大致相似的 区别在于处理 post 内容用的是 mysql real escape string 函数 而不是 addslashes 函数
  • DLS 深度受限搜索 狼羊 过河 问题 python 实现

    深度受限搜索 DLS 简单地说就是深度有限搜索 DFS 深度限制 limit DLS伪代码 实例 狼羊 过河 问题 3只羊和3头狼在河岸A 想要过河抵达河岸B 它们只有一艘船并且船上必须有1 2只生物 当 任意一边的狼的数量大于羊时 羊会被
  • 07模块和包(函数)

    一 函数的定义和调用 1 定义 函数 我们可以将在不同的地方要调用的相同的功能的代码进行分装 打包 定义一个函数 进行封装 例如 假设我们想在登录和注册时验证本人的手机号码是否正确时 我们可以将验证手机号码的过 程封装进函数里 之后进行使用
  • 算法 单链表删除重复元素

    1 删除重复的元素 保留一个 leetcode题目 代码 Definition for singly linked list public class ListNode int val ListNode next ListNode int
  • Golang非递归构建菜单树(O(n)时间复杂度,任意深度的递归树都能构造,适用于深层、大量数据的树结构构造)

    刚刚学习到Go的接口部分 希望对之前的基础部分 struct slice map 做一个简单的总结 希望各位Go语言方面的大佬给一点意见 非常感谢 编写过程中存在的一些疑惑 TreeNode结构中定义的Child 和SetChild 方法都