当前位置: 首页 > news >正文

【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)}}
}

相关文章:

  • 基于cnn卷积神经网络的车辆颜色检测识别-图像去雾-图像去雨(改进yolo目标检测-附代码)
  • 短视频矩阵系统----矩阵系统源码搭建(技术门槛?)
  • 【JavaEE初阶】 JVM类加载简介
  • 第四届信息通信与软件工程国际会议(ICICSE 2024)即将召开!
  • 【金三银四的季节看下Java ORM的走向和性能对比】总结
  • SQL学习十八~十九
  • 用WSGI发布flask到centos7.9
  • 20240307-2-前端开发校招面试问题整理HTML
  • 初学者如何使用QT新建一个包含UI界面的C++项目
  • 数据结构——lesson7二叉树 堆的介绍与实现
  • 【工具】Raycast – Mac提效工具
  • 2024年第十五届蓝桥杯第三期(校内)模拟赛题解
  • 迅速上手:CentOS 系统下 SSH 服务配置指南
  • Kafka面经
  • 调查数据显示,越来越多的企业正在增加对云存储预算
  • python3.6+scrapy+mysql 爬虫实战
  • 时间复杂度分析经典问题——最大子序列和
  • 【前端学习】-粗谈选择器
  • 【跃迁之路】【519天】程序员高效学习方法论探索系列(实验阶段276-2018.07.09)...
  • ECMAScript入门(七)--Module语法
  • es的写入过程
  • JavaScript标准库系列——Math对象和Date对象(二)
  • Java反射-动态类加载和重新加载
  • java概述
  • nodejs调试方法
  • php面试题 汇集2
  • quasar-framework cnodejs社区
  • Zsh 开发指南(第十四篇 文件读写)
  • 官方新出的 Kotlin 扩展库 KTX,到底帮你干了什么?
  • 猫头鹰的深夜翻译:JDK9 NotNullOrElse方法
  • 融云开发漫谈:你是否了解Go语言并发编程的第一要义?
  • 使用iElevator.js模拟segmentfault的文章标题导航
  • 问:在指定的JSON数据中(最外层是数组)根据指定条件拿到匹配到的结果
  • 我从编程教室毕业
  • 移动端解决方案学习记录
  • 再次简单明了总结flex布局,一看就懂...
  • Salesforce和SAP Netweaver里数据库表的元数据设计
  • 函数计算新功能-----支持C#函数
  • 曜石科技宣布获得千万级天使轮投资,全方面布局电竞产业链 ...
  • ​​快速排序(四)——挖坑法,前后指针法与非递归
  • ​LeetCode解法汇总1410. HTML 实体解析器
  • ​Z时代时尚SUV新宠:起亚赛图斯值不值得年轻人买?
  • !!【OpenCV学习】计算两幅图像的重叠区域
  • # 飞书APP集成平台-数字化落地
  • #### go map 底层结构 ####
  • #{}和${}的区别是什么 -- java面试
  • #我与Java虚拟机的故事#连载04:一本让自己没面子的书
  • (04)Hive的相关概念——order by 、sort by、distribute by 、cluster by
  • (1)常见O(n^2)排序算法解析
  • (2)MFC+openGL单文档框架glFrame
  • (八)Spring源码解析:Spring MVC
  • (一)UDP基本编程步骤
  • (译) 函数式 JS #1:简介
  • (转)shell中括号的特殊用法 linux if多条件判断
  • ***测试-HTTP方法