目录
力扣题号:94 144 145
1.前序遍历
前序遍历是根左右,先遍历的是根节点,先处理的也一定是根节点。先将根节点入栈,然后判断右孩子是不是为空,将右孩子入栈,再判断左孩子。之所以先将右孩子入栈,是因为栈先进后出。要优先弹出左孩子,就要优先将右孩子入栈。
代码如下:
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> list=new ArrayList<>();
Deque<TreeNode> s=new LinkedList<>();
if(root==null){
return list;
}
//将根节点入栈
s.push(root);
while(!s.isEmpty()){
//栈不为空
TreeNode node=s.pop();
list.add(node.val);
if(node.right!=null){
s.push(node.right);
}
if(node.left!=null){
s.push(node.left);
}
}
//list里面保存的是前序遍历的结点
return list;
}
2.后序遍历
后序遍历是“左右根”-----前序遍历是“根左右”,将前序遍历的顺序改变一下,先将左孩子入栈,得到的结果是“根右左”,再将得到的顺序翻转就是后序遍历的结果---左右根。
所以后序遍历可以在前序遍历的基础上改动一下代码。
代码如下:
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> list=new ArrayList<>();
Deque<TreeNode> s=new LinkedList<>();
if(root==null){
return list;
}
s.push(root); //先将根节点入栈
while(!s.isEmpty()){
TreeNode node=s.pop();
list.add(node.val);
if(node.left!=null){ //先将左孩子入栈
s.push(node.left);
}
if(node.right!=null){ //右孩子入栈
s.push(node.right);
}
}
Collections.reverse(list); //翻转结果
return list;
}
3.中序遍历
左根右,先遍历的一定是根节点,但是先处理的不是根节点,需要一个指针,遍历所有的结点,用栈保存所有遍历过的结点。左孩子为空,将自己出栈;右孩子为空,将栈中的元素出栈。
代码如下:
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> list=new ArrayList<>();
Deque<TreeNode> s=new LinkedList<>();
if(root==null){
return list;
}
//定义一个指针用来遍历二叉树
TreeNode cur=root;
while(cur!=null||!s.isEmpty()){ //栈不为空或者指针不为空
if(cur!=null){
s.push(cur); //指针将遍历过得所有元素都入栈
cur=cur.left; //遍历左孩子
}else{
cur=s.pop(); //左孩子为空,弹出自己
list.add(cur.val);
cur=cur.right; //遍历右孩子
}
}
return list;
}