前言
二叉树的遍历分为前序、中序和后序。可以通过遍历父节点的顺序来区别。前序遍历的顺序是父节点–左子节点–右子节点;中序遍历的顺序是左子节点–父节点–右子节点;后序遍历的顺序是左子节点–右子节点–父节点。通过递归和非递归的方式可以将其实现。
一,前序(根左右)
1,递归法
/**
* 递归法
*/
List<Integer> ret = new LinkedList<>();
public List<Integer> preorderTraversal(TreeNode root) {
if(root == null){
return ret;
ret.add(root.val);
preorderTraversal(root.left);
preorderTraversal(root.right);
return ret;
}
2,非递归法
(1)思路
将遍历的结果保存在List中,利用栈先进后出的特点,先将根入栈,当栈不为空出栈,对于前序遍历先将右孩子入栈,再入左孩子
(2)代码实现
/**
* 非递归法
*/
List<Integer> ret = new LinkedList<>();
public List<Integer> preorderTraversal(TreeNode root) {
if(root == null){
return ret;
}
Stack <TreeNode> stack = new Stack<>();
//根入栈
stack.push(root);
while (!stack.isEmpty()){
TreeNode node = stack.pop();//出栈
ret.add(node.val);
//先入右孩子,栈先进后出
if(node.right != null){
stack.push(node.right);
}
if(node.left != null){
stack.push(node.left);
}
}
return ret;
}
二,中序(左根右)
1,递归法
/**
* 递归法
*/
List <Integer> ret = new ArrayList<>();
public List<Integer> inorderTraversal(TreeNode root) {
if(root == null){
return ret;
}
inorderTraversal(root.left);
ret.add(root.val);
inorderTraversal(root.right);
return ret;
}
2,非递归法
(1)思路
将遍历的结果保存在List中,利用栈先进后出的特点,引入cur节点,当第二次访问根节点时,再保存根节点val,一路向左走,走到最左侧时,栈顶元素出栈,再遍历右节点
(2)代码实现
/**
* 非递归法
*/
List <Integer> ret = new ArrayList<>();
public List<Integer> inorderTraversal(TreeNode root) {
if (root == null) {
return ret;
}
Stack<TreeNode> stack = new Stack<>();
//cur表示当前访问的节点
TreeNode cur = root;
while (cur != null || !stack.isEmpty()){
//一路向左走到最左侧节点
while (cur != null){
stack.push(cur);
cur = cur.left;
}
//此时到达最左侧节点
cur = stack.pop();
ret.add(cur.val);
cur = cur.right;
}
return ret;
}
三,后序(左右根)
1,递归法
/**
* 递归法
*/
List <Integer> ret = new ArrayList<>();
public List<Integer> postorderTraversal(TreeNode root) {
if (root == null) {
return ret;
}
postorderTraversal(root.left);
postorderTraversal(root.right);
ret.add(root.val);
return ret;
}
2,非递归法
(1)思路
将遍历的结果保存在List中,利用栈先进后出的特点,引入cur和prev节点,其中cur为当前正在访问的节点,prev是最近一次访问结束的节点,先一路向左走,将cur压入栈,走到根节点时不能直接访问,判断右节点为空,或右节点已经访问过,再访问根节点,当右节点不为空,接着向右走
(2)代码实现
/**
* 非递归法
*/
List <Integer> ret = new ArrayList<>();
public List<Integer> postorderTraversal(TreeNode root) {
if (root == null) {
return ret;
}
Stack<TreeNode> stack = new Stack<>();
//当前正在访问的节点
TreeNode cur = root;
//最近一次访问结束的节点
TreeNode prev = null;
while (cur != null || !(stack.isEmpty())){
while (cur != null){
stack.push(cur);
cur = cur.left;
}
//此时走到最左侧节点,但不能访问根节点
// 要判断右节点是否为空,或右节点已经访问
cur = stack.pop();
if(cur.right == null || cur.right == prev){
ret.add(cur.val);
prev = cur; //更新prev的指向
cur = null;//再从栈顶去元素遍历
}else{
stack.push(cur);
cur = cur.right;//接着向右节点走
}
}
return ret;
}