今日题目:
- 二叉树的递归遍历
- 二叉树的迭代遍历
- 二叉树的统一遍历(可选)
今日总结
没啥好说的,要能把迭代遍历给背下来。使用栈,前序和后序是一样的,只需要做个反转。中序需要单独使用指针来记录需要处理的节点。
三种遍历方法
要点
1.栈空即终止
代码:
func preorderTraversal(root *TreeNode) []int {
if root == nil {
return nil
}
stack := []*TreeNode{root}
res := []int{}
for len(stack) > 0 {
node := stack[len(stack)-1]
res = append(res, node.Val)
stack = stack[:len(stack)-1]
if node.Right != nil {
stack = append(stack, node.Right)
}
if node.Left != nil {
stack = append(stack, node.Left)
}
}
return res
}
要点:
- 多了个reverse步骤
func postorderTraversal(root *TreeNode) []int {
if root == nil {
return nil
}
stack := []*TreeNode{}
res := []int{}
stack = append(stack, root)
for len(stack) > 0 {
node := stack[len(stack)-1]
stack = stack[:len(stack)-1]
res = append(res, node.Val)
if node.Left != nil {
stack = append(stack, node.Left)
}
if node.Right != nil {
stack = append(stack, node.Right)
}
}
reverse(res)
return res
}
func reverse(nums []int) {
for i := 0 ;i < len(nums)/2; i++{
nums[i], nums[len(nums)-i-1] = nums[len(nums)-i-1], nums[i]
}
return
}
要点:
- 只有中序遍历时,出入栈的节点和当前要处理的节点不一定一致,所以需要单独的指针。
- 循环终止条件包括了cur != nil,因为可能栈空了,但是还需要处理,比如根节点处理完左子树,切换到右子树时栈会为空
func inorderTraversal(root *TreeNode) []int {
if root == nil {
return nil
}
stack := []*TreeNode{}
res := []int{}
var cur *TreeNode = root
for cur != nil || len(stack) > 0 { //记住为啥判断条件是这两个
if cur != nil {
stack = append(stack, cur)
cur = cur.Left
} else {
cur = stack[len(stack)-1]
res = append(res, cur.Val)
stack = stack[:len(stack)-1]
cur = cur.Right //类似于前序遍历,栈顶弹出后你还需要将弹出节点的右子树添加进栈
}
}
return res
}