go语言实现二叉树的迭代后续遍历_二叉树后续遍历go语言(1)

	return res
}
left := midRecur(root.Left)
val := root.Val
right := midRecur(root.Right)

res = append(res, left...)
res = append(res, val)
res = append(res, right...)
return res

}


![](https://img-blog.csdnimg.cn/c774cd2a17664353a236e03dba3dd99e.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5aSn6ZSk54ix57yW56iL,size_7,color_FFFFFF,t_70,g_se,x_16)



## 二、🍻二叉树后序迭代遍历实现



> 
> 后序迭代遍历的实现,其实就是手动模拟后续遍历二叉树的递归实现。但是这里面有一点小坑的就是,后续遍历二叉树是需要先把左右子树遍历完了,再访问根节点的值。这个时候就需要定义一个变量额外记录访问过的变量。
> 
> 
> 


### 2.1🍺🍺🍺 二叉树定义


二叉树的定义是中规中矩喽~



type TreeNode struct {
Val int
Left *TreeNode
Right *TreeNode
}


### 2.2 🍖🍖🍖二叉树后续迭代遍历演化


这一块内容,就是逐步推演如何使用非递归遍历实现二叉树的后续。


#### 2.2.1 一杆子捅到底


通过前面的二叉树后续递归遍历的代码,我们了解到二叉树的后续遍历,就是先访问左子树,再访问右子树。从结果上,我们也可以了解到首先打印的是最左边,最下面的节点。根据栈先进后出的特点,所以我们了解到要先把所有的最左侧的节点灌到栈里面。



func postIteration(root *TreeNode) []int {
l := list2.New()
back:=root
var res []int
for l.Len() != 0 || back != nil {
for back!=nil {
l.PushBack(back)
back=back.Left
}
element := l.Back() //取出栈顶元素
top := element.Value.(*TreeNode) //类型转换

}
return res

}


### 2.3 🍟🍟🍟栈顶出数,路在何方


上面的代码呢,我们已经最左侧的节点,都丢到栈里面了。丢完了以后呢,我们要取出来开始遍历数据了呢。首先呢,通过栈递归呢,我们知道,我们第一次取出的这个数据,是没有左子树的,但是可能有右子树。如果有右子树,那么右子树也需要入栈。如果没有右子树,这个节点的数据就可以取出并移除。



func postIteration(root *TreeNode) []int {
l := list2.New()
back:=root
var res []int
for l.Len() != 0 || back != nil {
for back!=nil {
l.PushBack(back)
back=back.Left
}
element := l.Back() //取出栈顶元素
top := element.Value.(*TreeNode) //类型转换
//右子树不为空,那么右子树也需要入栈
if top.Right!=nil {
back=top.Right
}else {
//右子树为空,取出值
res = append(res, top.Val)
l.Remove(element)
back=nil //取出来值的时候,要把需要入栈的子树置位nil,否则会死循环。
}
}
return res
}


 **执行结果:意外的是,上面这段代码又陷入死循环。**


**死循环原因:上述代码,增加了一个逻辑判断,就是当栈顶元素E的右子树存在时,开始对右子树进行入栈。但是呀,但是呀,这里有一个问题啦,那就是右子树入栈的时候,并没有把原来栈顶元素E弹出来呀!也就是说,这段代码,又卡死在一个循环里。**


### 2.3 🍟🍟🍟一次就好,整太多没用


闲言少叙,再接上文。这个代码死循环的原因就在于对栈顶元素右子树的判断。举一个简单例子,对一个后序遍历为235的树,当栈中的数据只剩跟5的时候,会判断有没有右子树,有的话,把右子树3入栈。当3出栈,栈中只有根5的时候,这个根5又会判断有没有右子树,有的话,又会把3入栈,循环往复,栈就溢出了。程序就崩溃了。


那这个问题的根源在哪,在于这个根5,他访问不知道右子树被访问过,来来回回,折磨电脑,就是打印不出。那么解决问题的办法就是让根有意义,让根知道谁被访问过~  
  



func postIteration(root *TreeNode) []int {
l := list2.New()
back := root
var res []int
var visited *TreeNode //增加一个标志位,确认节点是否被访问过
for l.Len() != 0 || back != nil {
for back != nil {
l.PushBack(back)
back = back.Left
}
element := l.Back() //取出栈顶元素
top := element.Value.(*TreeNode) //类型转换
//右子树不为空,那么右子树也需要入栈,且top的右子树不能被访问过,
if top.Right != nil && visited != top.Right {
back = top.Right
} else
{
res = append(res, top.Val)
l.Remove(element)
visited =top
//这里就没有需要入栈的元素了,要不然取出来,又扔进去了
back = nil
}
}
return res
}


leetCode代码测试成功哦~ 


![](https://img-blog.csdnimg.cn/371c7211914a4cf497467d78d4c25d6f.png)


 



## 三、🍏🍏🍏总结


        纸上得来终觉浅,绝知此事要躬行。我会尽量在我的博客里面留下我自己思考的内容💪🏻⛽️~



> 
> 🧧🧧🧧感谢诸位大佬的阅读,点个关注,收藏一下呗~
> 
> 


![img](https://img-blog.csdnimg.cn/img_convert/9e3997d6d1de34f5f95923f895204b59.png)
![img](https://img-blog.csdnimg.cn/img_convert/7f5b24913df0a8398293fcb98cf2d979.png)
![img](https://img-blog.csdnimg.cn/img_convert/79637ea839efb3bda0b0707376135cc8.png)

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!**

g-LKZV8y8S-4702074697930)]
[外链图片转存中...(img-DfseXY8G-4702074697931)]
[外链图片转存中...(img-KNMXNwJw-4702074697931)]

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!**

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值