题目
二叉树的前序,中序,后序遍历
Depth First Traversals:
(a) Inorder (Left, Root, Right) : 4 2 5 1 3
(b) Preorder (Root, Left, Right) : 1 2 4 5 3
(c) Postorder (Left, Right, Root) : 4 5 2 3 1
Breadth First or Level Order Traversal : 1 2 3 4 5
https://www.geeksforgeeks.org/tree-traversals-inorder-preorder-and-postorder/
递归解法
/* Given a binary tree, print its nodes according to the
"bottom-up" postorder traversal. */
void printPostorder(Node node)
{
if (node == null)
return;
// first recur on left subtree
printPostorder(node.left);
// then recur on right subtree
printPostorder(node.right);
// now deal with the node
System.out.print(node.key + " ");
}
/* Given a binary tree, print its nodes in inorder*/
void printInorder(Node node)
{
if (node == null)
return;
/* first recur on left child */
printInorder(node.left);
/* then print the data of node */
System.out.print(node.key + " ");
/* now recur on right child */
printInorder(node.right);
}
/* Given a binary tree, print its nodes in preorder*/
void printPreorder(Node node)
{
if (node == null)
return;
/* first print data of node */
System.out.print(node.key + " ");
/* then recur on left sutree */
printPreorder(node.left);
/* now recur on right subtree */
printPreorder(node.right);
}
前序非递归解法
我的尝试:
我的尝试问题有问题,我在while循环的时候把左侧节点都存入list,我以为这些左侧节点都是root,只要从stack取出来,然后添加上右侧节点就可以了,其实不对,比如在 1-null-2-3,情况下,加入list的节点是右侧节点2,不是左侧节点,因为没有左侧节点。如下图所示:
所以这个情况下, 我的输出结果多一个2.
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> list=new ArrayList();
Stack<TreeNode> stack=new Stack<TreeNode>();
TreeNode curr=root;
while(curr!=null){
list.add(curr.val);
stack.push(curr);
//[1,null,2,3],left不存在情况无法cover
if(curr.left!=null){
curr=curr.left;
}
else{
curr=curr.right;
}
}
while(stack.empty()==false){
TreeNode tmpNode=(TreeNode)stack.pop();
TreeNode tmpRight=tmpNode.right;
if(tmpRight!=null){
list.add(tmpRight.val);
}
}
return list;
}
}
正确解法:
在重新整理思路后,写了如下算法,一次通过leetcode测试,为自己喝彩!!!
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> list=new ArrayList();
if(root==null) return list;
Stack<TreeNode> stack=new Stack<TreeNode>();
TreeNode curr=root;
list.add(curr.val);
if(curr.right!=null){
stack.push(curr.right);
}
if(curr.left!=null){
stack.push(curr.left);
}
while(stack.empty()==false){
TreeNode tmpNode=(TreeNode)stack.pop();
list.add(tmpNode.val);
if(tmpNode.right!=null){
stack.push(tmpNode.right);
}
if(tmpNode.left!=null){
stack.push(tmpNode.left);
}
}
return list;
}
}
我写的代码可以优化一下,第一段判断右左是否存在,并且入stack的操作,跟后面孩子节点的代码其实是重复的 ,优化整合一下:
1. 判断根节点是否为空,为空,返回空list,不为空,入stack
2. 循环从stack取出stack顶部元素,先访问该node,然后判断是否有左右节点,如果有,先入右,后入左。直到为空
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> list=new ArrayList();
if(root==null) return list;
Stack<TreeNode> stack=new Stack<TreeNode>();
stack.push(root);
while(stack.empty()==false){
TreeNode tmpNode=(TreeNode)stack.pop();
list.add(tmpNode.val);
if(tmpNode.right!=null){
stack.push(tmpNode.right);
}
if(tmpNode.left!=null){
stack.push(tmpNode.left);
}
}
return list;
}
public List<Integer> postorderTraversal(TreeNode root) {
//不可以写list,方法addFirst找不到
LinkedList<Integer> list=new LinkedList<>();
Stack<TreeNode> stack=new Stack();
if(root==null){
return list;
}
stack.push(root);
while(!stack.isEmpty()){
TreeNode treeNode=stack.pop();
//为了反转list,所以利用linkedlist的addFirst接口
list.addFirst(treeNode.val);
if(treeNode.left!=null){
stack.push(treeNode.left);
}
if(treeNode.right!=null){
stack.push(treeNode.right);
}
}
return list;
}
}
中序非递归解法
中序遍历,写对了两个关键部分代码:
一个是指针curr从root开始,一直左侧遍历到底,直到为空,第二个是stack弹出元素,访问。但是不知道怎么处理右侧节点。看了solution后,恍然大悟。修改curr指向curr.right。
整理思路后,写代码如下:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
Stack<TreeNode> stack=new Stack();
List<Integer> list=new ArrayList();
TreeNode curr=root;
while(curr!=null||!stack.isEmpty()){
//如果右子树不为空,又是从左侧一路到底
while(curr!=null){
stack.push(curr);
curr=curr.left;
}
curr=stack.pop();
list.add(curr.val);
//我的代码只是少这个关键一行,处理右子树
curr=curr.right;
}
return list;
}
}
注意:
stack.pop()弹出的对象也是curr,就是当前指针指向的对象。我刚开始写的时候新定义了一个TreeNode。
后序非递归写法
后序非递归写法,于先序遍历相似,先序遍历是从顶到底,先左后右,后序遍历是从底到顶,先左后右。
所以需要反转,为了便于比较,我把代码放在先序遍历中。