zoukankan      html  css  js  c++  java
  • 算法基础之二叉树遍历(前中后)

    二叉树

    前序遍历

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

    中序遍历

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

    后序遍历

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

    解法

    递归

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

    迭代

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

    代码

    // 递归模板
    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
    }
  • 相关阅读:
    Java第九次作业
    Java第八次作业
    Java第七次作业
    Java第六次作业
    Java第五次作业
    Java第四次作业
    Java第三次作业
    Java第二次作业
    Java第一次作业
    高级工程师和初级工程师之间的一道坎
  • 原文地址:https://www.cnblogs.com/hzpeng/p/15084833.html
Copyright © 2011-2022 走看看