携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第21天,点击查看活动详情
二叉树迭代遍历
推荐阅读:二叉树的迭代遍历
前序遍历
前序遍历是先处理中间节点在处理左右节点。(中左右)
- 写入根节点,不断迭代左节点直到叶子节点
- 从左叶子节点往上,判断是否有右子节点
- 有则入栈,再次迭代,进行同样的操作
- 没有,则左节点层数向上。
- 直到切片为空或者没有右子节点,遍历完成
func preorderTraversal(root *TreeNode) []int {
stack:=[]*TreeNode{}
ans:=[]int{}
node:=root
for node!=nil||len(stack)>0{//栈不为空
//判断当前节点是否为空
for node!=nil{
ans=append(ans,node.Val)
stack=append(stack,node)
node=node.Left
}
//拿到当前层的左节点
node=stack[len(stack)-1]
stack=stack[:len(stack)-1]//弹出当前节点,层数向上,下次取就是根节点
node=node.Right//迭代右节点
}
return ans
}
感觉思想有点像递归!!!团子的感觉!!🤣😅
中序遍历
中序遍历是先处理左节点,然后处理中节点和右节点(左中右)
其实思想与前序差不多,只是需要先遍历到左叶子节点,然后逐渐往上遍历中节点,之后处理右节点。具体的可以通过代码理解!
func inorderTraversal(root *TreeNode) []int {
stack:=[]*TreeNode{}
node:=root
ans:=[]int{}
for node!=nil||len(stack)>0{
for node!=nil{//遍历当前节点的左节点到左叶子节点
stack=append(stack,node)
node=node.Left
}
node=stack[len(stack)-1]//拿到当前层的左节点
stack=stack[:len(stack)-1]//弹出当前节点,层数向上,下一次取就是根节点
ans=append(ans,node.Val)//获取当前节点值
node=node.Right//迭代右节点
}
return ans
}
你会发现前序和中序的区别就是获取当前值的位置不同
后序遍历
后序遍历是先处理左节点,然后就处理右节点,之后处理中节点(左右中)
前序遍历是中左右
后序遍历是左右中
有没有发现一个特点!!!😋😋😋快想想!
你把前序遍历的顺序改成中右左,之后再首尾交换,是不是就是左右中了,这不就是后序遍历吗?!!🎉🎉🎉
- 改变前序遍历的顺序为中右左
- 遍历后的值首尾交换
func postorderTraversal(root *TreeNode) []int {
stack:=[]*TreeNode{}
ans:=[]int{}
node:=root
for node!=nil||len(stack)>0{
for node!=nil{//遍历中节点
ans=append(ans,node.Val)
stack=append(stack,node)
node=node.Right//遍历右节点
}
node=stack[len(stack)-1]//拿到当前层的右节点
stack=stack[:len(stack)-1]//层数向上,下一次取就是根节点
node=node.Left//迭代左节点
}
Reverse(ans)
return ans
}
func Reverse(num []int){//完成首尾交换工作
for i:=0;i<len(num)/2;i++{
num[i],num[len(num)-i-1]=num[len(num)-i-1],num[i]
}
}
有没有一种很神奇的感觉!!!
上面一种方法比较取巧了!
下面是比较正式的后序遍历
func postorderTraversal(root *TreeNode) (res []int) {
stk := []*TreeNode{}
var prev *TreeNode
//左右中
for root != nil || len(stk) > 0 {
for root != nil {
stk = append(stk, root)
root = root.Left
//遍历到左叶子结点
}
root = stk[len(stk)-1]
stk = stk[:len(stk)-1]
// 需要先写入右孩子节点 判断右孩子是否为空 为空就填值 不为空就放回栈 遍历右孩子的子树
//防止再次遍历一次右节点,需要记录之前遍历的节点(右节点)
if root.Right == nil || root.Right == prev {
res = append(res, root.Val)
prev = root
root = nil
} else {
stk = append(stk, root)
root = root.Right
}
}
return
}
前中后序的遍历用一种代码全部完成了!!!!三种遍历的代码变化都不是很大!!!!理解后,你就可以秒杀二叉树遍历了!!快夸夸团子!!😘😘😘
练手题目:
参考资料: