代码随想录算法训练营Day14
二叉树节点结构定义
二叉树节点结构定义如下:
type TreeNode struct {
Val int
Left *TreeNode
Right *TreeNode
}
二叉树递归遍历
前序遍历算法设计步骤
- 确定递归函数的参数和返回值:
- 参数:当前节点指针
- 返回值:前序遍历序列数组
- 确定终止条件:
- 当前节点为空时,返回空数组
- 确定单层递归的逻辑:
- 将当前节点的值加入遍历序列数组
- 递归遍历左子树
- 递归遍历右子树
前序遍历代码实现
func preorderTraversal(root *TreeNode) []int {
if root == nil {
return []int{}
}
result := []int{root.Val}
result = append(result, preorderTraversal(root.Left)...)
result = append(result, preorderTraversal(root.Right)...)
return result
}
中序遍历算法设计步骤
- 确定递归函数的参数和返回值:
- 参数:当前节点指针
- 返回值:中序遍历序列数组
- 确定终止条件:
- 当前节点为空时,返回空数组
- 确定单层递归的逻辑:
- 递归遍历左子树
- 将当前节点的值加入遍历序列数组
- 递归遍历右子树
中序遍历代码实现
func inorderTraversal(root *TreeNode) []int {
if root == nil {
return []int{}
}
result := []int{}
result = append(result, inorderTraversal(root.Left)...)
result = append(result, root.Val)
result = append(result, inorderTraversal(root.Right)...)
return result
}
后序遍历算法设计步骤
- 确定递归函数的参数和返回值:
- 参数:当前节点指针
- 返回值:后序遍历序列数组
- 确定终止条件:
- 当前节点为空时,返回空数组
- 确定单层递归的逻辑:
- 递归遍历左子树
- 递归遍历右子树
- 将当前节点的值加入遍历序列数组
后序遍历的Go语言实现代码
func postorderTraversal(root *TreeNode) []int {
if root == nil {
return []int{}
}
result := []int{}
result = append(result, postorderTraversal(root.Left)...)
result = append(result, postorderTraversal(root.Right)...)
result = append(result, root.Val)
return result
}
二叉树迭代遍历
前序遍历的迭代法算法设计步骤
- 确定递归函数的参数和返回值
- 参数:根节点指针
- 返回值:前序遍历序列数组
- 确定终止条件
- 当当前节点为空时,终止遍历
- 确定单层递归的逻辑
- 使用栈来模拟递归过程
- 将根节点压入栈中
- 循环直到栈为空,每次弹出栈顶节点,将节点值加入遍历序列数组
- 如果节点的右子树不为空,将右子树压入栈中
- 如果节点的左子树不为空,将左子树压入栈中
前序遍历的迭代法代码实现
func preorderTraversal(root *TreeNode) []int {
var result []int
if root == nil {
return result
}
stack := []*TreeNode{root}
for len(stack) > 0 {
node := stack[len(stack)-1]
stack = stack[:len(stack)-1]
result = append(result, node.Val)
if node.Right != nil {
stack = append(stack, node.Right)
}
if node.Left != nil {
stack = append(stack, node.Left)
}
}
return result
}
中序遍历的迭代法算法设计步骤
- 确定递归函数的参数和返回值
- 参数:根节点指针
- 返回值:中序遍历序列数组
- 确定终止条件
- 当当前节点为空且栈为空时,终止遍历
- 确定单层递归的逻辑
- 使用栈来模拟递归过程
- 从根节点开始,将所有左子节点压入栈中
- 弹出栈顶节点,将节点值加入遍历序列数组
- 如果节点有右子节点,将右子节点及其所有左子节点压入栈中
中序遍历的迭代法算法代码实现
func inorderTraversal(root *TreeNode) []int {
var result []int
stack := []*TreeNode{}
node := root
for node != nil || len(stack) > 0 {
for node != nil {
stack = append(stack, node)
node = node.Left
}
node = stack[len(stack)-1]
stack = stack[:len(stack)-1]
result = append(result, node.Val)
node = node.Right
}
return result
}
后序遍历的迭代法算法设计步骤
- 确定递归函数的参数和返回值
- 参数:根节点指针
- 返回值:后序遍历序列数组
- 确定终止条件
- 当当前节点为空且栈为空时,终止遍历
- 确定单层递归的逻辑
- 使用两个栈来模拟递归过程
- 将根节点压入第一个栈中
- 从第一个栈中弹出节点,并将节点值压入第二个栈中
- 如果节点有左子节点,将左子节点压入第一个栈中
- 如果节点有右子节点,将右子节点压入第一个栈中
后序遍历的迭代法算法代码实现
func postorderTraversal(root *TreeNode) []int {
var result []int
if root == nil {
return result
}
stack1 := []*TreeNode{root}
stack2 := []*TreeNode{}
for len(stack1) > 0 {
node := stack1[len(stack1)-1]
stack1 = stack1[:len(stack1)-1]
stack2 = append(stack2, node)
if node.Left != nil {
stack1 = append(stack1, node.Left)
}
if node.Right != nil {
stack1 = append(stack1, node.Right)
}
}
for i := len(stack2) - 1; i >= 0; i-- {
result = append(result, stack2[i].Val)
}
return result
}