LeetCode 94 Inorder 问题描述
思路
中序遍历: 按照 左结点 根节点 右结点的顺序
递归实现 : preorder方法实现按照 左结点 根节点 右结点的顺序加入。以左结点为根的子树和 以右结点为根的子树 遍历也是由inorder方法实现。
非递归实现 :通过一个栈,从根节点开始入栈,如果当前结点不为空或者栈不为空,进入循环,只要一直存在左节点就一直入栈,不存在左节点就出栈访问当前结点,当前结点设置为出栈节点的右节点, 然后继续循环遍历
java实现
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
// //way1递归
// class Solution {
// List<Integer> result=new ArrayList<Integer>();
// public List<Integer> inorderTraversal(TreeNode root) {
// inorder(root);
// return result;
// }
// private void inorder(TreeNode node){
// if(node==null)
// return;
// if(node.left!=null)
// inorder(node.left);//左
// result.add(node.val);//根
// if(node.right!=null)
// inorder(node.right);//右
// }
// }
// way2 非递归方式
// 通过一个栈,从根节点开始入栈,只要一直存在左节点就一直入栈,不存在左节点就出栈访问节点值,然后继续遍历出栈那个节点的右节点
public class Solution {
public List < Integer > inorderTraversal(TreeNode root) {
List < Integer > result = new ArrayList < > ();
Stack < TreeNode > stack = new Stack < > ();
TreeNode current = root;
while (current!=null || !stack.isEmpty()){
//一直找到最左边的结点
while (current!=null) {
stack.push(current);
current = current.left;
}
current=stack.pop();
result.add(current.val);
current=current.right;
}
return result;
}
}
LeetCode 144 Preorder问题描述
思路
前序遍历: 按照 根节点 左结点 右结点的顺序
递归实现1 (遍历法): preorder方法实现按照 根节点 左结点 右结点的顺序加入。以左结点为根的子树和 以右结点为根的子树 遍历也是由preorder方法实现。
递归实现2(分治法) :按照 根节点 整个左子树 真个右子树的顺序加入,将这个分为左右两部分,最后合并。(中序和后续遍历也可以这样实现,本文中没有写)
- 两种方式的共同之处:都是递归实现
- 两种方式的区别:
(1)第一种方法存放结果的是一个全局变量,只有这一个结果容器存放结果。
第二种方式:每次都新建立一个容器,相当于局部的解,是有意义的,最后将所有容器的结果合并到结果容器
(2)参数和返回值不同
(遍历法是从上到下,分治法是从下往上)
非递归实现 :通过一个栈,从根节点开始入栈,如果栈不为空,进入循环,出栈访问当前结点,若当前结点的右结点不为空,右结点入栈,若当前结点的左结点不为空,左结点入栈,然后进入下一次循环(因为栈是先进后出 所以先加入右结点 再加入左结点 弹出的时候先弹出左结点 再弹出右结点)
java实现
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
// // way1 递归方式1
// class Solution {
// List<Integer> result=new ArrayList<Integer>();
// public List<Integer> preorderTraversal(TreeNode root) {
// //4.递归的调用
// preorder(root);
// return result;
//
// }
//
// //1.递归的定义 :返回以node为跟的二叉树的前序遍历
// private void preorder(TreeNode node){
// //3.递归的出口
// if(node==null)
// return;
// //2.递归的拆解
// result.add(node.val);
// if(node.left!=null)
// preorder(node.left);
// if(node.right!=null)
// preorder(node.right);
//
// }
// }
// //// way2 递归方式2:分治的思想(divide and conquer)
// //1.递归的定义:返回以root为跟的二叉树的前序遍历
// class Solution {
// public List<Integer> preorderTraversal(TreeNode root) {
// List<Integer> result=new ArrayList<Integer>();
// //分 divide
// List<Integer>left=new ArrayList<Integer>();
// List<Integer>right=new ArrayList<Integer>();
// if(root==null)
// return result;
// if(root.left!=null)
// left=preorderTraversal(root.left);
// if(root.right!=null)
// right=preorderTraversal(root.right);
// //和 conquer(merge)
// result.add(root.val);
// result.addAll(left);
// result.addAll(right);
// return result;
// }
// }
// way3 非递归方式
//通过一个栈,从根节点开始入栈,如果栈不为空,进入循环,出栈访问当前结点,若当前结点的右结点不为空,右结点入栈,若当前结点的左结点不为空,左结点入栈,然后进入下一次循环(因为栈是先进后出 所以先加入右结点 再加入左结点 弹出的时候先弹出左结点 再弹出右结点)
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> result=new ArrayList<Integer>();
if(root==null)
return result;
Stack<TreeNode> stack=new Stack<TreeNode>();
stack.push(root);
TreeNode tempNode=null;
while (!stack.isEmpty()){
tempNode=stack.pop();
result.add(tempNode.val);
//因为栈是先进后出 所以先加入右结点 再加入左结点 弹出的时候先弹出左结点 再弹出右结点
if(tempNode.right!=null)
stack.push(tempNode.right);
if(tempNode.left!=null)
stack.push(tempNode.left);
}
return result;
}
}
LeetCode 145 Postorder 问题描述
思路
前序遍历: 按照 左结点 右结点 根节点 的顺序
递归实现 : postorder方法实现按照 左结点 右结点 根节点的顺序加入。以左结点为根的子树和 以右结点为根的子树 遍历也是由postorder方法实现。
非递归实现1 :根节点压栈 当栈不为空,将弹出元素放在第一个(利用LinkedList的 addFirst方法),压栈按照先左结点后右结点的顺序,如此循环
非递归实现2:
java实现
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
// //way1 递归
// class Solution {
// List<Integer> result=new ArrayList<Integer>();
// public List<Integer> postorderTraversal(TreeNode root) {
// postorder(root);
// return result;
// }
// private void postorder(TreeNode node){
// if(node==null)
// return;
// if(node.left!=null)
// postorder(node.left);
// if(node.right!=null)
// postorder(node.right);
// result.add(node.val);
// }
// }
// way2 非递归方式1
// //根节点压栈 当栈不为空,将弹出元素放在第一个,压栈按照先左结点后右结点的顺序,如此循环
// class Solution {
// public List<Integer> postorderTraversal(TreeNode root) {
// LinkedList<Integer> result = new LinkedList<>();
// if(root == null) return result;
// TreeNode curr = root;
// Stack<TreeNode> stack = new Stack<>();
// stack.push(root);
// while(!stack.isEmpty()){
// curr = stack.pop();
// result.addFirst(curr.val);
// if(curr.left != null)
// stack.push(curr.left);
// if(curr.right != null)
// stack.push(curr.right);
// }
// return result;
// }
// }
// way2 非递归方式2
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<Integer>();
Stack<TreeNode> stack = new Stack<TreeNode>();
TreeNode pre = null;//pre用来记录刚刚加入result的结点,可以用来判定右侧是否已经访问过了
TreeNode current = root;
while(current != null || !stack.isEmpty()){
if(current != null){ //当前结点不为空
//当前结点入栈
stack.push(current);
//当前结点指向左结点
current = current.left;
}else{ //当前结点为空
//获取栈顶元素
TreeNode top = stack.peek();
//栈顶结点右侧为空或者右侧已经访问(top.right == pre 说明top.right已经加入res里了)
if(top.right == null || top.right == pre){
result.add(top.val);//把栈顶的结点加入result中
stack.pop();//栈顶的结点弹出
pre = top;//pre记录刚刚加入result的结点
}else{
//栈顶结点右侧不为空且右侧没有被访问
current = top.right; //当前结点指向右结点
}
}
}
return result;
}
}
来源:CSDN
作者:ying______
链接:https://blog.csdn.net/weixin_44135282/article/details/103799549