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


    二叉树

    前序遍历

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

    中序遍历

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

    后序遍历

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

    解法

    递归

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

    迭代

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

    代码

    // 递归模板
    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
    }
  • 相关阅读:
    (5)基于协同过滤推荐算法的图书推荐研究
    (4)推荐系统评测方法和指标分析
    (3)浅析机器学习在推荐系统中的应用
    (2)协同过滤推荐算法概述 摘要
    (1)推荐系统概述 -- 摘要
    30+简约时尚的Macbook贴花
    20+非常棒的Photoshop卡通设计教程
    20+WordPress手机主题和插件【好收藏推荐】
    30+WordPress古典风格的主题-古典却不失时尚
    配置FCKeditor_2.6.3+fckeditor-java-2.4
  • 原文地址:https://www.cnblogs.com/hzpeng/p/15084833.html
Copyright © 2020-2023  润新知