最近写了一下关于二叉树的三种遍历算法的递归以及非递归实现,以及层次遍历算法实现
先序遍历递归实现
/**
* 先序遍历,根》左》右
*/
public void beforeTraverse(TreeNode root) {
if (root == null) {
return;
}
System.out.print(root.val + "->");
if (root.left != null) {
beforeTraverse(root.left);
}
if (root.right != null) {
beforeTraverse(root.right);
}
}
先序遍历非递归实现
/**
* 通过栈遍历二叉树,先序(思想就是:入栈即记录)
*/
public List<String> beforeTraverseByStack(TreeNode root) {
List<Integer> ans = new ArrayList<>();
// 栈
Deque<TreeNode> stack = new ArrayDeque<>();
while (root != null || !stack.isEmpty()) {
// 1. 左节点全部入栈,并且记录它们的值放到结果集中
while (root != null) {
stack.push(root);
ans.add(root.val);
root = root.left;
}
// 2. 依次出栈,并且看出栈的节点是否有右节点,有右节点则还需一直寻找其左节点入栈(同上)
root = stack.pop().right;
}
return ans;
}
中序遍历递归实现
/**
* 中序遍历,左》根》右
*/
public void middleTraverse(TreeNode root) {
if (root.left != null) {
middleTraverse(root.left);
}
System.out.print(root.val + "->");
if (root.right != null) {
middleTraverse(root.right);
}
}
中序遍历非递归实现
/**
* 通过栈遍历二叉树,中序(思想就是:出栈即记录)
*/
public List<String> middleTraverseByStack(TreeNode root) {
List<Integer> ans = new ArrayList<>();
// 栈
Deque<TreeNode> stack = new ArrayDeque<>();
while (root != null || !stack.isEmpty()) {
// 1. 先左节点全部入栈
while (root != null) {
stack.push(root);
root = root.left;
}
// 2. 一个个节点出栈,出栈的同时将他们放到结果集中,并且判断其有没有右节点,若有右节点则需将其左节点全部加入栈中(同上)
root = stack.pop();
ans.add(root.val);
root = root.right;
}
return ans;
}
后序遍历递归实现
/**
* 后序遍历,左》右》根
*/
public void afterTraverse(TreeNode root) {
if (root.left != null) {
afterTraverse(root.left);
}
if (root.right != null) {
afterTraverse(root.right);
}
System.out.print(root.val + "->");
}
后序遍历非递归实现
/**
* 通过栈遍历二叉树,后序
*/
public List<String> afterTraverseByStack(TreeNode root) {
List<Integer> ans = new ArrayList<>();
Deque<TreeNode> stack = new ArrayDeque<>();
// 2. 一个个节点出栈,并且判断其有没有右节点,没有右节点直接放入结果集中,若有右节点则需将其左节点全部加入栈中(同上)
// 放入结果集中的条件:没有右节点或者右节点已经全部遍历完
// 那么需要一个标识位,标识上一位放入结果集的节点是什么(即遍历完)
TreeNode prev = null;
while (root != null || !stack.isEmpty()) {
// 1. 先左节点全部入栈
while (root != null) {
stack.push(root);
root = root.left;
}
TreeNode node = stack.pop();
// 没有右节点,放入结果集;或者右节点已经遍历完
if (node.right == null || node.right == prev) {
ans.add(node.val);
prev = node;
} else {
// 还有右节点,重新入栈,并且其左孩子继续入栈
stack.push(node);
root = node.right;
}
}
return ans;
}
层次遍历算法实现
/**
* 层次(顺序)遍历,一层一层,从左向右
* 需要引入队列这种数据结构,队列:先进先出,头进尾出
* 因为既需要找到一个结点的左结点又需要找到右结点
*/
public List<String> orderTraverse(TreeNode root) {
// 使用集合代替队列,先进先出(出队列就是移除第0个元素)
Queue<TreeNode> queue = new LinkedList<>();
List<String> result = new ArrayList<>(); // 接受结果
if (root == null) {
return result;
}
list.add(root);
while (!queue.isEmpty()) {
TreeNode node = queue.poll();
result.add(node.val);
if (node.left != null) {
queue.add(node.left);
}
if (node.right != null) {
queue.add(node.right);
}
}
return result;
}
总的来说,非递归算法就是引入辅助数据结构栈(或者其他),利用他们特殊的结构先进后出(其他)的特点,完成按要求的遍历
关于树的很多算法都是由他们变形而来的,但还是需要灵活的转变思维才能解决相应的问题