【golang】二叉树的遍历

本文使用golang实现二叉树的遍历,包含以下7种方法。

  • 深度优先遍历
    • 先序遍历
      • 递归法
      • 非递归法
    • 中序遍历
      • 递归法
      • 非递归法
    • 后序遍历
      • 递归法
      • 非递归法
  • 广度优先遍历

二叉树节点定义:

type Node struct {Val   intLeft  *NodeRight *Node
}

深度优先遍历

先序遍历

定义
1) 访问根节点;
2) 先序遍历左子树;
3) 先序遍历右子树。

递归实现

func preorder(root *Node, consume func(*Node)) {if root == nil {return}consume(root)preorder(root.Left, consume)preorder(root.Right, consume)
}

非递归实现
思路:使用一个栈实现
1)将根节点压入栈;
2)栈中弹出一个节点,访问该节点;
3)将该节点的右孩子、左孩子依次压入栈;
4)重复步骤2~3直至完成步骤3时栈为空。

栈实现:

type Stack struct {values []*Node
}func (s *Stack) Push(node *Node) {if s.values == nil {s.values = make([]*Node, 0)}s.values = append(s.values, node)
}func (s *Stack) Pop() *Node {sl := len(s.values)if sl <= 0 {return nil}node := s.values[sl-1]s.values = s.values[:sl-1]return node
}func (s *Stack) IsEmpty() bool {return len(s.values) == 0
}
func preorder(root *Node, consume func(*Node)) {if root == nil {return}stack := Stack{}stack.Push(root)for node := stack.Pop(); node != nil; node = stack.Pop() {consume(node)if node.Right != nil {stack.Push(node.Right)}if node.Left != nil {stack.Push(node.Left)}}
}

中序遍历

定义
1) 中序遍历左子树;
2) 访问根节点;
3) 中序遍历右子树。

递归实现

func inorder(root *Node, consume func(*Node)) {if root == nil {return}inorder(root.Left, consume)consume(root)inorder(root.Right, consume)
}

非递归实现
思路:使用一个栈实现
1) 将根节点及其所有直系左孩子压入栈(直系左孩子:其父节点也是左孩子);
2) 栈弹出一个节点,访问该节点;
3) 若弹出的节点有右孩子,则将右孩子视为根节点执行步骤1;
4) 重复步骤2~3,直至栈为空。

func inorder(root *Node, consume func(*Node)) {if root == nil {return}stack := Stack{}pushAllLeft(root, &stack)for !stack.IsEmpty() {node := stack.Pop()consume(node)if node.Right != nil {pushAllLeft(node.Right, &stack)}}
}func pushAllLeft(root *Node, stack *Stack) {for node := root; node != nil; node = node.Left {stack.Push(node)}
}

后序遍历

定义
1) 后序遍历左子树;
2) 后序遍历右子树;
3) 访问根节点。

递归实现

func postorder(root *Node, consume func(*Node)) {if root == nil {return}postorder(root.Left, consume)postorder(root.Right, consume)consume(root)
}

非递归实现
思路:使用2个栈实现
1) 将根节点压入栈1;
2) 栈1弹出一个节点,将其左孩子、右孩子依次压入栈1;
3) 将步骤2弹出的节点压入栈2;
4) 重复步骤2~3,直至执行完步骤3时栈1为空;
5) 栈2弹出一个节点,并访问该节点;
6) 重复步骤5,直至栈2为空。

func postorder(root *Node, consume func(*Node)) {if root == nil {return}stack1 := Stack{}stack2 := Stack{}stack1.Push(root)for !stack1.IsEmpty() {node := stack1.Pop()stack2.Push(node)if node.Left != nil {stack1.Push(node.Left)}if node.Right != nil {stack1.Push(node.Right)}}for !stack2.IsEmpty() {consume(stack2.Pop())}
}

广度优先遍历

定义:按从上往下、从左往右的顺序来遍历
思路:使用一个队列实现
1) 将根节点加入队尾;
2) 从队列头取出一个节点,访问该节点;
3) 将该节点的左孩子、右孩子依次加入队尾;
4) 重复步骤2~3,直至执行完步骤3时队列为空。

func widthorder(root *Node, consume func(*Node)) {if root == nil {return}queue := make([]*Node, 0)queue = append(queue, root)for len(queue) > 0 {node := queue[0]queue = queue[1:]consume(node)if node.Left != nil {queue = append(queue, node.Left)}if node.Right != nil {queue = append(queue, node.Right)}}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/729839.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C语言实现回调函数

C语言实现回调函数 一、回调函数概念1.1 什么叫函数指针 二、回调函数案例 一、回调函数概念 回调函数就是一个被作为参数传递的函数。在C语言中&#xff0c;回调函数只能使用函数指针实现&#xff0c;在C、Python、ECMAScript等更现代的编程语言中还可以使用仿函数或匿名函数…

IDEA启动项目读取nacos乱码导致启动失败

新安装的2023社区版IDEA,启动项目报错。 forest: interceptors: - com.gdsz.b2b.frontend.api.Interceptors.ApiInterceptor org.yaml.snakeyaml.error.YAMLException: java.nio.charset.MalformedInputException: Input length 1 at org.yaml.snakeyaml.reader.S…

Java面试题总结10之MySQL索引和锁

索引的基本原理 把无需的数据变成有序的查询 1&#xff0c;把创建了索引的列的内容进行排序 2&#xff0c;对排序结果生成倒排表 3&#xff0c;到倒排表内容上拼上数据地址链 4&#xff0c;在查询的时候&#xff0c;先拿到倒排表内容&#xff0c;再取出数据地址链&#xf…

error: cannot bind non-const lvalue reference of type 解决方法

error: cannot bind non-const lvalue reference of type 解决方法 问题来源解决方法 问题来源 使用direct_visual_lidar_calibration时需要安装Iridescence 编译时出现如下错误 /home/flipper/iridescence/src/glk/glsl_shader.cpp:289:36: error: cannot bind non-const lv…

7-3 前世档案(Python)

网络世界中时常会遇到这类滑稽的算命小程序&#xff0c;实现原理很简单&#xff0c;随便设计几个问题&#xff0c;根据玩家对每个问题的回答选择一条判断树中的路径&#xff08;如下图所示&#xff09;&#xff0c;结论就是路径终点对应的那个结点。 现在我们把结论从左到右顺序…

基于Leatlet标注Geojson下载器实现

在上一篇文章中&#xff0c;我们学习了Leaflet的基础知识&#xff0c;包括如何创建地图、添加图层等。在本文中&#xff0c;我们将深入学习Leaflet中标注的创建和管理&#xff0c;包括如何添加标注、自定义标注图标、创建图层组、批量添加和删除标注、为标注添加属性和弹出框等…

手机卡丢失了怎么办?挂失与补办全攻略来了

现在人人都离不开手机&#xff0c;手机改变了我们的生活&#xff0c;但是有时我们可能会遇到手机卡丢失或被盗的情况。这时&#xff0c;及时挂失并补办新的手机卡至关重要&#xff0c;以确保个人信息安全和通信畅通。这里小编将为您提供详细的手机卡挂失与补办流程指南&#xf…

day38 动态规划part1

509. 斐波那契数 简单 斐波那契数 &#xff08;通常用 F(n) 表示&#xff09;形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始&#xff0c;后面的每一项数字都是前面两项数字的和。也就是&#xff1a; F(0) 0&#xff0c;F(1) 1 F(n) F(n - 1) F(n - 2)&#xff0c;…

VS配置开发与远程调试笔记

先简单写一下&#xff0c;后续详细补充 场景&#xff1a;本地机器开发&#xff0c;虚拟机调试 准备工作&#xff1a; 由于要将生成的文件生成在虚拟机&#xff0c;避免反复拷贝&#xff0c;直接配置虚拟机共享文件夹进行写入&#xff0c;步骤如下&#xff1a; 虚拟机打开网…

Vue3:ref和reactive实现响应式数据

一、情景说明 在Vue2中&#xff0c;我们已经知道数据的响应式&#xff0c;是什么含义 就是&#xff0c;在data块中&#xff0c;定义的变量&#xff0c;在页面中引用后 任何地方修改了该变量&#xff0c;页面中引用的变量会立即显示最新数值。 这块&#xff0c;我们学习了 插值…

Leetcode : 1122. 数组的相对排序

思路&#xff1a;计数排序&#xff0c;然后根据计数的数组序列重构数组&#xff0c;针对多余的数组元素采取sort函数进行升序排列加在末尾即可。 #include <iostream> #include <vector> #include <algorithm>using namespace std;class Solution { public:v…

ChatGPT消息发不出去了?我找到解决方案了

现象 今天忽然发现 ChatGPT无法发送消息&#xff0c;能查看历史对话&#xff0c;但是无法发送消息。 猜测原因 出现这个问题的各位&#xff0c;应该都是点击登录后顶部弹窗邀请[加入多语言 alapha 测试]了&#xff0c;并且语言选择了中文&#xff0c;抓包看到ab.chatgpt.com…

win11修改主机mac地址

很多时候&#xff0c;为了限制恶意的蹭流浪&#xff0c;除了分配固定的ip地址外&#xff0c;还限制mac地址。只有mac与ip一致&#xff0c;才能上网冲浪 网络适配器中修改 搜索“控制面板”打开 控制面板 > 网络和Internet > 网络和共享中心 >查看网络状态和任务>…

【操作系统学习笔记】文件管理1.9

【操作系统学习笔记】文件管理1.9 参考书籍: 王道考研 视频地址: Bilibili 文件保护 口令保护 为文件设置一个口令&#xff0c;用户请问访问该文件时必须提供口令交由系统验证 优点 保存口令的空间开销小验证口令的时间开销小 缺点 正确的口令存放在系统内部&#xff0c;不…

kafka 可视化工具

kafka可视化工具 随着科技发展&#xff0c;中间件也百花齐放。平时我们用的redis&#xff0c;我就会通过redisInsight-v2 来查询数据&#xff0c;mysql就会使用goland-ide插件来查询&#xff0c;都挺方便。但是kafka可视化工具就找了半天&#xff0c;最后还是觉得redpandadata…

【框架】React和Vue的异同

1. 前言 React对于原生JS要求会高一级&#xff0c;国外React用的多&#xff0c;国内Vue用的多。 2. 共同点 组件化函数式编程 &#xff08;vue3函数式编程、vue2声明式编程&#xff09;单向数据流&#xff0c;数据驱动视图VirtualDOM Diff算法操作DOM社区成熟&#xff0c;…

在哪里能找到抖音短视频素材?推荐热门的抖音短视频素材下载资源

哎呦喂&#xff0c;小伙伴们&#xff0c;是不是在短视频的大海里划船&#xff0c;想找到那颗能让你起飞的珍珠&#xff0c;但又觉得素材难寻如针海捞针&#xff1f;别急&#xff0c;今天我就来给你们送上几个超实用的宝藏素材网站&#xff0c;让你的短视频创作不再愁素材 1&am…

Docker容器的操作

目录 运行容器 查看容器 查看容器详细信息 删除容器 启动容器 停止容器 重启容器 暂停容器 激活容器 杀死容器 进入容器 常用 查看容器的日志 拷贝容器的文件到本地 容器改名 查看容器资源 查看容器内部的进程 监测容器发生的事件 检测容器停止以后的反回值…

网站维护中的风险及应对策略

在现代数字化时代&#xff0c;企业对网站的维护至关重要&#xff0c;但维护期间也存在着风险和潜在威胁。本文将探讨网站维护中可能面临的风险&#xff0c;并提供一些应对策略以降低这些风险对企业的影响。 一、数据泄露&#xff1a; 在网站维护期间&#xff0c;未经适当保护的…

RK3568驱动指南|第十三篇 输入子系统第(137章 初识input子系统)

瑞芯微RK3568芯片是一款定位中高端的通用型SOC&#xff0c;采用22nm制程工艺&#xff0c;搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码&#xff0c;支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU&#xff0c;可用于轻量级人工…