写在前面:
关于二叉树,具体可参考二叉树理论基础篇。
二叉树的遍历方式分为前序(中左右)、中序(左中右)、后序(左右中)、层序遍历(从上到下,从左到右)四种。
二叉树核心的两种遍历方式:深度优先遍历(DFS)、广度优先遍历(BFS),进一步拓展如下:
深度优先遍历
前序遍历(递归法,迭代法)
中序遍历(递归法,迭代法)
后序遍历(递归法,迭代法)
广度优先遍历
层次遍历(迭代法)
递归法解题步骤:
(1)确定递归函数的参数和返回值: 确定哪些参数是递归的过程中需要处理的,那么就在递归函数里加上这个参数, 并且还要明确每次递归的返回值是什么进而确定递归函数的返回类型。
(2)确定终止条件: 写完了递归算法, 运行的时候,经常会遇到栈溢出的错误,就是没写终止条件或者终止条件写的不对,操作系统也是用一个栈的结构来保存每一层递归的信息,如果递归没有终止,操作系统的内存栈必然就会溢出。
(3)确定单层递归的逻辑: 确定每一层递归需要处理的信息。在这里也就会重复调用自己来实现递归的过程。
递归的实现就是:
每一次递归调用都会把函数的局部变量、参数值和返回地址等压入调用栈中,然后递归返回的时候,从栈顶弹出上一次递归的各项参数,所以这就是递归为什么可以返回上一层位置的原因。
迭代法:
迭代法与递归法两种方式是等价的,区别在于递归的时候隐式地维护了一个栈,而我们在迭代的时候需要显式地将这个栈模拟出来,其余的实现与细节都相同。
LeetCode144 二叉树的前序遍历
代码:
/**
* Definition for a binary tree node.
* public class TreeNode {
* public int val;
* public TreeNode left;
* public TreeNode right;
* public TreeNode(int val=0, TreeNode left=null, TreeNode right=null) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
//递归法:
public class Solution {
public IList<int> PreorderTraversal(TreeNode root) {
IList<int> list = new List<int>();
Traversal(root, list);
return list;
}
public void Traversal(TreeNode root, IList<int> list)
{
if (root == null) return;
list.Add(root.val);
Traversal(root.left, list);
Traversal(root.right, list);
}
}
//迭代法:
public class Solution {
public IList<int> PreorderTraversal(TreeNode root) {
IList<int> list = new List<int>();
Stack<TreeNode> stack = new Stack<TreeNode>();
if(root == null) return list;
stack.Push(root);
while (stack.Count > 0)
{
TreeNode temp = stack.Pop();
list.Add(temp.val);
if (temp.right != null)
{
stack.Push(temp.right);
}
if (temp.left != null)
{
stack.Push(temp.left);
}
}
return list;
}
}
LeetCode145 二叉树的后序遍历
代码:
/**
* Definition for a binary tree node.
* public class TreeNode {
* public int val;
* public TreeNode left;
* public TreeNode right;
* public TreeNode(int val=0, TreeNode left=null, TreeNode right=null) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
//递归法:
public class Solution {
public IList<int> PostorderTraversal(TreeNode root) {
IList<int> list = new List<int>();
Traversal(root, list);
return list;
}
public void Traversal(TreeNode root, IList<int> list)
{
if (root == null) return;
Traversal(root.left, list); ;
Traversal(root.right, list);
list.Add(root.val);
}
}
//迭代法:
public class Solution {
public IList<int> PostorderTraversal(TreeNode root) {
IList<int> list = new List<int>();
Stack<TreeNode> stack = new Stack<TreeNode>();
//空节点用来存储
TreeNode pre = null;
if (root == null) return list;
while (root != null||stack.Count != 0)
{
//找到最左边的节点
while (root != null)
{
stack.Push(root);
root = root.left;
}
//确定root为最左边节点
root = stack.Pop();
if (root.right == null || root.right == pre)
{
list.Add(root.val);
pre = root;
root = null;
}
//找到右边节点
else
{
stack.Push(root);
root = root.right;
}
}
return list;
}
}
LeetCode94 二叉树的中序遍历
代码:
/**
* Definition for a binary tree node.
* public class TreeNode {
* public int val;
* public TreeNode left;
* public TreeNode right;
* public TreeNode(int val=0, TreeNode left=null, TreeNode right=null) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
//递归法:
public class Solution {
public IList<int> InorderTraversal(TreeNode root) {
List<int> list = new List<int>();
Traversal(root, list);
return list;
}
public void Traversal(TreeNode root, IList<int> list)
{
if (root == null) return;
Traversal(root.left, list);
list.Add(root.val);
Traversal(root.right, list);
}
}
//迭代法:
public class Solution {
public IList<int> InorderTraversal(TreeNode root) {
List<int> list = new List<int>();
Stack<TreeNode> stack = new Stack<TreeNode>();
TreeNode cur = null;
while (stack.Count != 0 || root != null)
{
while (root != null)
{
stack.Push(root);
root = root.left;
}
root = stack.Pop();
list.Add(root.val);
root = root.right;
}
return list;
}
}