Loading

算法基础之二叉树遍历(前中后)

二叉树

前序遍历

先访问根节点,再前序遍历左子树,再前序遍历右子树

中序遍历

先中序左子树,在访问根节点,再中序遍历右子树

后序遍历

先后序遍历左子树,再后序遍历右子树,再访问跟节点

解法

递归

三种遍历方式递归代码基本一致,根据遍历顺序调整结果保存与递归代码顺序即可

迭代

采用压栈的方式,核心代码基本也是一致的,只是压栈和结果保存的时机稍微一点区别

代码

// 递归模板
func recursionTraversal(root *TreeNode) (res []int) {
    if root == nil{
        return nil
    }
    var recursion func(root *TreeNode)
    recursion = func(root *TreeNode){
        if root == nil{
            return
        }
        // 前序遍历
        res = append(res,root.Val)
        postorder(root.Left)
        postorder(root.Right)
        // 中序遍历
        postorder(root.Left)
        res = append(res,root.Val)
        postorder(root.Right)
        // 后序遍历
        postorder(root.Left)
        postorder(root.Right)
        res = append(res,root.Val)
    }
    recursion(root)
    return 
}

// 前序迭代遍历
func preorderTraversal(root *TreeNode) []int{
	if root == nil {
		return nil
	}
	// 最终返回结果
	result := make([]int,0)
	// 堆栈存储中间节点
	stack := make([]*TreeNode,0)
	// 当二叉树左右遍历节点都为空,堆栈无节点退出循环
	for root != nil || len(stack) != 0 {
		// 循环 保存根节点 将节点保存栈中 继续读取左节点
		for root != nil {
			result = append(result,root.Val)
			stack = append(stack,root)
			root = root.Left
		}
		// 上方循环无左节点了 执行stack pop操作 赋值 root 右节点继续遍历
		node := stack[len(stack)-1]
		stack = stack[:len(stack)-1]
		root = node.Right
	}
	return result
}

// 中序迭代遍历
func inorderTraversal(root *TreeNode)  []int {
	result := make([]int,0)
	if root == nil{
		return result
	}
	stack := make([]*TreeNode,0)
	for len(stack) > 0 || root != nil {
		// 存储访问元素,一直向左
		for root != nil{
			stack = append(stack,root)
			root = root.Left
		}
		val := stack[len(stack)-1]
		stack = stack[:len(stack)-1]
		result = append(result,val.Val)
		root = val.Right
	}
	return result
}

// 后序迭代遍历
func postorderTraversal(root *TreeNode)	[]int {
	if root == nil{
		return nil
	}
	result := make([]int,0)
	stack := make([]*TreeNode,0)
	var lastVisit *TreeNode
	for root != nil || len(stack) != 0 {
		for root != nil{
			stack = append(stack,root)
			root = root.Left
		}
		node := stack[len(stack)-1]
		// 确保不存在右节点或右节点已经弹出后弹出根元素
		if node.Right == nil || node.Right == lastVisit{
			stack = stack[:len(stack)-1]
			result = append(result,node.Val)
			// 标识节点已弹出
			lastVisit = node
		}else{
			root = node.Right
		}
	}
	return result
}
posted @ 2021-07-31 18:01  励码万言  阅读(52)  评论(0编辑  收藏  举报