算法-二叉树011-二叉树的前、中、后序遍历

在这里插入图片描述

二叉树

首先,二叉树是一种「数据结构」。简单来说,就是一个包含节点,以及它的左右孩子的一种数据结构。

遍历方式

  • 先序遍历,根节点-> 左孩子 -> 右孩子 的方式遍历,即「先序遍历」,每次遍历跟节点
    1 -> 2 -> 4 -> 5 -> 3 -> 6 -> 7
  • 中序遍历,左孩子-> 根节点->右孩子 的方式遍历,即「中序遍历」,遍历结果为
    4 -> 2 -> 5 -> 1 -> 6 -> 3 -> 7
  • 后序遍历,左孩子->右孩子->根节点 的方式遍历,即「后序遍历」,遍历结果为
    4 -> 5 -> 2 -> 6 -> 7 -> 3 -> 1
  • 层级遍历,就是按照每一层从左向右遍历,遍历结果
    1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7

相关题目

相关题目

这里是 4 道相关题目:

  1. 144.二叉树的前序遍历
  2. 94. 二叉树的中序遍历
  3. 145. 二叉树的后序遍历
  4. 102. 二叉树的层序遍历

这四道题目描述是相似的,就是给定一个二叉树,让我们使用一个数组来返回遍历结果,首先来看递归解法。

递归法

构造数据结构

type TreeNode struct {
	Val int
	Left *TreeNode
	Right *TreeNode
}

var res []int

root := &TreeNode{
		Val:   1,
		Left:  &TreeNode{
			Val:   2,
			Left:  &TreeNode{
				Val:   4,
				Left:  nil,
				Right: nil,
			},
			Right: &TreeNode{
				Val:   5,
				Left:  nil,
				Right: nil,
			},
		},
		Right: &TreeNode{
			Val:   3,
			Left:  &TreeNode{
				Val:   6,
				Left:  nil,
				Right: nil,
			},
			Right: &TreeNode{
				Val:   7,
				Left:  nil,
				Right: nil,
			},
		},
	}

1、前序遍历

//-- ----------------------------
//--> @Description 前序遍历
//--> @Param
//--> @return
//-- ----------------------------
func preorderTraversal(root *TreeNode){
	if root == nil{
		return
	}
	//先加入跟节点,在加入左孩子,在加入右孩子
	res = append(res,root.Val)
	preorderTraversal(root.Left)
	preorderTraversal(root.Right)
	return
}

[1 2 4 5 3 6 7]

2、中序遍历

//-- ----------------------------
//--> @Description 中序遍历
//--> @Param
//--> @return
//-- ----------------------------
func inorderTraversal(root *TreeNode){
	if root == nil {
		return
	}
	//先加入左孩子,在加入跟节点,在加入右孩子
	inorderTraversal(root.Left)
	res = append(res,root.Val)
	inorderTraversal(root.Right)
}
[4 2 5 1 6 3 7]

3、后序遍历

//-- ----------------------------
//--> @Description 后序遍历
//--> @Param
//--> @return
//-- ----------------------------
func postTraversal(root *TreeNode){
	if root == nil{
		return
	}
	postTraversal(root.Left)
	postTraversal(root.Right)
	res = append(res,root.Val)

}
[4 5 2 6 7 3 1]

迭代法

迭代法主要用到了golang的list数据结构
前序遍历

  • 首先我们将右侧压入队列
  • 在将左侧雅茹队列
  • 将root写入res
  • 取出尾部,不断遍历左侧,右侧
  • 再次押入右侧,左侧

1、前序遍历

前序遍历:中左右
压栈顺序:右左中

//-- ----------------------------
//--> @Description 前序遍历
//--> @Param
//--> @return
//-- ----------------------------
func scanPreorderTraversal(root *TreeNode)(res []int){
	if root == nil {
		return nil
	}
	var stack = list.New()
	stack.PushBack(root.Right)
	stack.PushBack(root.Left)
	res=append(res,root.Val)
	for stack.Len()>0 {
		e:=stack.Back()
		stack.Remove(e)
		//e是Element类型,其值为e.Value.由于Value为接口,所以要断言
		node := e.Value.(*TreeNode)
		if node==nil{
			continue
		}
		res=append(res,node.Val)
		stack.PushBack(node.Right)
		stack.PushBack(node.Left)
	}
	return res

}
[1 2 4 5 3 6 7]

2、中序遍历

//-- ----------------------------
//--> @Description
//--> @Param
//--> @return
//-- ----------------------------
func scanInorderTraversal(root *TreeNode) []int {
	rootRes:=[]int{}
	if root==nil{
		return nil
	}
	stack:=list.New()
	node:=root
	//先将所有左节点找到,加入栈中
	for node!=nil{
		stack.PushBack(node)
		node=node.Left
	}
	//其次对栈中的每个节点先弹出加入到结果集中,再找到该节点的右节点的所有左节点加入栈中
	for stack.Len()>0{
		e:=stack.Back()
		node:=e.Value.(*TreeNode)
		stack.Remove(e)
		//找到该节点的右节点,再搜索他的所有左节点加入栈中
		rootRes=append(rootRes,node.Val)
		node=node.Right
		for node!=nil{
			stack.PushBack(node)
			node=node.Left
		}
	}
	return rootRes
}
[4 2 5 1 6 3 7]

3、后序遍历

迭代法后序遍历
后续遍历:左右中
压栈顺序:中右左(按照前序遍历思路),再反转结果数组

func postorderTraversal(root *TreeNode) (res []int) {
	if root == nil {
		return nil
	}
	var stack = list.New()
	stack.PushBack(root.Left)
	stack.PushBack(root.Right)
	res=append(res,root.Val)
	for stack.Len()>0 {
		e:=stack.Back()
		stack.Remove(e)
		node := e.Value.(*TreeNode)//e是Element类型,其值为e.Value.由于Value为接口,所以要断言
		if node==nil{
			continue
		}
		res=append(res,node.Val)
		stack.PushBack(node.Left)
		stack.PushBack(node.Right)
	}
	for i:=0;i<len(res)/2;i++{
		res[i],res[len(res)-i-1] = res[len(res)-i-1],res[i]
	}
	return res
}
[4 5 2 6 7 3 1]

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

a...Z

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值