二叉树遍历及算法实现
-
遍历定义
指按某条搜索路线遍访每个结点且不重复(又称周游)。
-
遍历用途
它是树结构插入、删除、修改、查找和排序运算的前提,是二叉树一切运算的基础和核心。
-
遍历方法
牢记一种约定,对每个结点的查看都是“先左后右” 。
限定先左后右,树的遍历有三种实现方案:
DLR LDR LRD
先 (根)序遍历 中 (根)序遍历 后(根)序遍历
n DLR — 先序遍历,即先根再左再右
n LDR — 中序遍历,即先左再根再右
n LRD — 后序遍历,即先左再右再根
注:“先、中、后”的意思是指访问的结点D是先于子树出现还是后于子树出现。
从递归的角度看,这三种算法是完全相同的,或者说这三种遍历算法的访问路径是相同的,只是访问结点的时机不同。
package main import ( "fmt" "reflect" ) type BinaryNode struct { Data interface{} //数据 lChild *BinaryNode //左子树 rChild *BinaryNode //右子树 } //创建二叉树 func (node *BinaryNode) Create() { node = new(BinaryNode) } //先序遍历 func (node *BinaryNode) PreOrder() { if node == nil { return } //DLR — 先序遍历,即先根再左再右 fmt.Println(node.Data) //递归遍历左子树 node.lChild.PreOrder() //递归遍历右子树 node.rChild.PreOrder() } //中序遍历 func (node *BinaryNode) MidOrder() { if node == nil { return } //LDR — 中序遍历,即先左再根再右 //递归遍历左子树 node.lChild.MidOrder() //打印数据 fmt.Println(node.Data) //递归遍历右子树 node.rChild.MidOrder() } //后序遍历 func (node *BinaryNode) RearOrder() { if node == nil { return } //LRD — 后序遍历,即先左再右再根 //递归遍历左子树 node.lChild.RearOrder() //递归遍历右子树 node.rChild.RearOrder() //打印数据 fmt.Println(node.Data) } //二叉树高度 深度 func (node *BinaryNode) TreeHeight() int { if node == nil { return 0 } //进入下一层遍历 lh := node.lChild.TreeHeight() rh := node.rChild.TreeHeight() if lh > rh { lh++ return lh } else { rh++ return rh } } //二叉树叶子节点个数 //叶子节点是没有后继的节点 func (node *BinaryNode) LeafCount(num *int) { if node == nil { return } //判断没有后继的节点为叶子节点 if node.lChild == nil && node.rChild == nil { (*num)++ } node.lChild.LeafCount(num) node.rChild.LeafCount(num) } //二叉树数据查找 func (node *BinaryNode) Search(Data interface{}) { if node == nil { return } //== 不支持slice 和 map //reflect.DeepEqual() if reflect.TypeOf(node.Data) == reflect.TypeOf(Data) && node.Data == Data { fmt.Println("找到数据", node.Data) return } node.lChild.Search(Data) node.rChild.Search(Data) } //二叉树销毁 func (node *BinaryNode) Destroy() { if node == nil { return } node.lChild.Destroy() node.lChild = nil node.rChild.Destroy() node.rChild = nil node.Data = nil } //二叉树反转 //如果想反转二叉树 二叉树必须是一个满二叉树 func (node *BinaryNode) Reverse() { if node == nil { return } //交换节点 多重赋值 node.lChild, node.rChild = node.rChild, node.lChild node.lChild.Reverse() node.rChild.Reverse() } //二叉树拷贝 func (node *BinaryNode) Copy() *BinaryNode { if node == nil { return nil } lChild:=node.lChild.Copy() rChild:=node.rChild.Copy() //创建写节点 拷贝数据 newNode:=new(BinaryNode) newNode.Data=node.Data newNode.lChild=lChild newNode.rChild=rChild return newNode }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
2016-11-16 git的常用命令