总结的四种二叉树遍历算法(递归和非递归)

四种遍历树的算:前序、中序、后序、层次遍历(正向,反向,Z字形遍历)

遍历二叉树算法基本操作是访问结点,不论按哪一种次序进行遍历,对含n个结点的二叉树时间复杂度都为O(n)。

 

前序遍历:

递归方式:


                  void preorder_recursive(Bitree T)      /* 先序遍历二叉树的递归算法 */ 
                        { 
                           if (T) { 
                              visit(T);          /* 访问当前结点 */ 
                              preorder_recursive(T->lchild);   /* 访问左子树 */ 
                              preorder_recursive(T->rchild);   /* 访问右子树 */ 
                           } 
                        }


递归方式:

- LeetCode

/**

 * Definition for a binary tree node.

 * public class TreeNode {

 *     int val;

 *     TreeNode left;

 *     TreeNode right;

 *     TreeNode(int x) { val = x; }

 * }

 */

public class Solution {

    public List<Integer> preorderTraversal(TreeNode root) {

        List<Integer> res=new ArrayList<Integer>();

        Stack<TreeNode> s=new Stack<TreeNode>();

        if(root==null)return res;

        s.push(root);

        while(!s.empty()){

            TreeNode node=s.pop();

            res.add(node.val);

            if(node.right!=null){

                s.push(node.right);

            }

            if(node.left!=null){

                s.push(node.left);

            }

            

        }

        return res;

    }

}

这里注意到:一开始就是将栈顶元素出栈,并先将右节点再将左节点放入栈中(之间是if...if关系,不是if...else关系,因为左右节点的父节点已经出栈了,一定要一次性将左右入栈,否则后面无法再入)

不能写成下面这样,否则死循环:

public class Solution {

    public List<Integer> preorderTraversal(TreeNode root) {

        List<Integer> res=new ArrayList<Integer>();

        Stack<TreeNode> s=new Stack<TreeNode>();

        if(root==null)return res;

        s.push(root);

        res.add(root.val);

        while(!s.empty()){

            TreeNode node=s.peek();

            if(node.left==null&&node.right==null){

                s.pop();

            }else if(node.left!=null){

                res.add(node.left.val);

                s.push(node.left);

            }else if(node.right!=null){

                res.add(node.right.val);

                s.push(node.right);

            }

        }

        return res;

    }

}

中序遍历

递归方式

                  void inorder_recursive(Bitree T)      /* 中序遍历二叉树的递归算法 */ 
                        { 
                           if (T) { 
                              inorder_recursive(T->lchild);   /* 访问左子树 */ 
                              visit(T);          /* 访问当前结点 */ 
                              inorder_recursive(T->rchild);   /* 访问右子树 */ 
                           } 
                        }

非递归方式

- LeetCode

            /**

 * Definition for a binary tree node.

 * public class TreeNode {

 *     int val;

 *     TreeNode left;

 *     TreeNode right;

 *     TreeNode(int x) { val = x; }

 * }

 */

public class Solution {

    public List<Integer> inorderTraversal(TreeNode root) {

        List<Integer> res=new ArrayList<Integer>();

        Stack<TreeNode> stack=new Stack<TreeNode>();

        if(root==null)return res;

        TreeNode node=root;

        while(node!=null||!stack.empty()){

            if(node != null){

    stack.push(node);

    node = node.left;

    }else{

    node = stack.pop();

    res.add(node.val);

    node = node.right;

    }

        }

        return res;

        

    }

}

后序遍历:

递归方式:

                  void postorder_recursive(Bitree T)      /* 中序遍历二叉树的递归算法 */ 
                        { 
                           if (T) { 
                              postorder_recursive(T->lchild);   /* 访问左子树 */ 
                              postorder_recursive(T->rchild);   /* 访问右子树 */ 
                              visit(T);             /* 访问当前结点 */ 
                           } 
                        }

非递归方式 

- LeetCode

可以修改原树:

/**

 * Definition for a binary tree node.

 * public class TreeNode {

 *     int val;

 *     TreeNode left;

 *     TreeNode right;

 *     TreeNode(int x) { val = x; }

 * }

 */

public class Solution {

    public List<Integer> postorderTraversal(TreeNode root) {

        List<Integer> res=new ArrayList<Integer>();  

        if(root==null) return res;  

        Stack<TreeNode> sta=new Stack<TreeNode>();  

  

        sta.push(root);  

  

        while(!sta.empty()) {  

            TreeNode top = sta.peek();  

            if(top.left!=null) {  

                sta.push(top.left);  

                top.left = null;  

            } else if(top.right!=null) {  

                sta.push(top.right);  

                top.right = null;  

            } else {  

                sta.pop();  

                res.add(top.val);  

            }  

        }  

  

        return res;  

    }

}

不可修改原树:

算法如下:

1)如果根节点非空,将根节点加入到栈中。

2)如果栈不空,取栈顶元素(暂时不弹出),

如果(左子树已访问过或者左子树为空),且(右子树已访问过或右子树为空),则弹出栈顶节点,将其值加入数组,并进行第三步。

如果左子树不为空,切未访问过,则将左子节点加入栈中,并标左子树已访问过。并进行第三步(不继续判断右子树,这是关键)。

如果右子树不为空,切未访问过,则将右子节点加入栈中,并标右子树已访问过。并进行第三步。

3)重复第二步,直到栈空。

/**

 * Definition for a binary tree node.

 * public class TreeNode {

 *     int val;

 *     TreeNode left;

 *     TreeNode right;

 *     TreeNode(int x) { val = x; }

 * }

 */

 class TreeNodeWrapped {

      TreeNode node;

      boolean isLeftVisit=false;

      boolean isRightVisit=false;

      TreeNodeWrapped(TreeNode node) {

          

          this.node=node;

         

      }

  

  }

public class Solution {

    public List<Integer> postorderTraversal(TreeNode root) {

        List<Integer> res=new ArrayList<Integer>();  

        if(root==null) return res;  

        Stack<TreeNodeWrapped> stack=new Stack<TreeNodeWrapped>();  

        TreeNodeWrapped rootWrapped=new TreeNodeWrapped(root);

        stack.push(rootWrapped);  

  

        while(!stack.empty()) {  

            TreeNodeWrapped top = stack.peek();  

            if((top.node.left==null||top.isLeftVisit==true)&&(top.node.right==null||top.isRightVisit==true)){

                res.add(top.node.val);

                stack.pop();

            }else{

                if(top.node.left!=null&&top.isLeftVisit==false){

                    stack.push(new TreeNodeWrapped(top.node.left));

                    top.isLeftVisit=true;

                }else if(top.node.right!=null&&top.isRightVisit==false){

                    stack.push(new TreeNodeWrapped(top.node.right));

                    top.isRightVisit=true;

                }

            }

            

        }  

  

        return res;  

    }

}

层次遍历

- LeetCode

用一个队列

/**

 * Definition for a binary tree node.

 * public class TreeNode {

 *     int val;

 *     TreeNode left;

 *     TreeNode right;

 *     TreeNode(int x) { val = x; }

 * }

 */

 import java.util.ArrayList;

import java.util.List;

import java.util.concurrent.LinkedBlockingQueue;

public class Solution {

    public List<List<Integer>> levelOrder(TreeNode root) {

        List<List<Integer>> res=new ArrayList<List<Integer>>();

        LinkedBlockingQueue queue=new LinkedBlockingQueue();

        if(root==null)return res;

        queue.add(root);

        int count=1;

        while(!queue.isEmpty()){

        int count2=0;

        List<Integer> temp=new ArrayList<Integer>();

        while(count>0&&!queue.isEmpty()){

        

            TreeNode head=(TreeNode) queue.poll();

            temp.add(head.val);

            if(head.left!=null){

            queue.add(head.left);

            count2++;

            }

            if(head.right!=null){

            queue.add(head.right);

            count2++;

            }

            count--;

        }

        count=count2;

        res.add(temp);

        }

        

        return res;

    }

}

 

递归

/**

 * Definition for a binary tree node.

 * public class TreeNode {

 *     int val;

 *     TreeNode left;

 *     TreeNode right;

 *     TreeNode(int x) { val = x; }

 * }

 */

 import java.util.ArrayList;

import java.util.List;

public class Solution {

    

    List<List<Integer>> res=null;

    public List<List<Integer>> levelOrder(TreeNode root) {

         res=new ArrayList<List<Integer>>();

         func(root,0);

         return res;

        

    }

    

     void func(TreeNode node,int level){

        if(node==null)return;

        

        if(res.size()==level){

            res.add(new ArrayList<Integer>());

        }

        res.get(level).add(node.val);

        func(node.left,level+1);

        func(node.right,level+1);

 

    }

}

 

反向层次遍历

- LeetCode

/**

 * Definition for a binary tree node.

 * public class TreeNode {

 *     int val;

 *     TreeNode left;

 *     TreeNode right;

 *     TreeNode(int x) { val = x; }

 * }

 */

public class Solution {

    public List<List<Integer>> levelOrderBottom(TreeNode root) {

     LinkedList<List<Integer>> list = new LinkedList<List<Integer>>();

     addLevel(list, 0, root);

     return list;

    }

    

    private void addLevel(LinkedList<List<Integer>> list, int level, TreeNode node) {

     if (node == null) return;

     if (list.size()-1 < level) list.addFirst(new LinkedList<Integer>());

     list.get(list.size()-1-level).add(node.val);

     addLevel(list, level+1, node.left);

     addLevel(list, level+1, node.right);

    }

}

这里注意:用 LinkedList而不用ArrayList,是因为list.addFirst,list.add会快一点,但list.size(),list.get会慢

分层Z字形遍历

- LeetCode

/**

 * Definition for a binary tree node.

 * public class TreeNode {

 *     int val;

 *     TreeNode left;

 *     TreeNode right;

 *     TreeNode(int x) { val = x; }

 * }

 */

 import java.util.Deque;

import java.util.LinkedList;

import java.util.List;

public class Solution {

    public List<List<Integer>> zigzagLevelOrder(TreeNode root) {

        List<List<Integer>> result = new LinkedList<>();

        if (root == null) {

            return result;

        }

        // 遍历标志,0表示从左到右,1表示从右到左

        int flag = 0;

        TreeNode node;

        // 记录每一层的元素

        List<Integer> lay = new LinkedList<>();

        // 双向队列,当作栈来使用,记录当前层待处理结点

        Deque<TreeNode> stack = new LinkedList<>();

        // 记录下一层待处理结点

        Deque<TreeNode> nextStack = new LinkedList<>();

        stack.add(root);

        while (!stack.isEmpty()) {

            // 删除栈顶元素

            node = stack.removeLast();

            // 结果入队

            lay.add(node.val);

            // 如果当前是从左到右遍历,按左子树右子树的顺序添加

            if (flag == 0) {

                if (node.left != null) {

                    nextStack.addLast(node.left);

                }

                if (node.right != null) {

                    nextStack.addLast(node.right);

                }

            }else {// 如果当前是从右到左遍历,按右子树左子树的顺序添加

                if (node.right != null) {

                    nextStack.addLast(node.right);

                }

                if (node.left != null) {

                    nextStack.addLast(node.left);

                }

            }

            // 当前层已经处理完了

            if (stack.isEmpty()) {

                Deque<TreeNode> temp = nextStack;

                nextStack = stack;

                stack = temp;

                // 标记下一层处理的方向

                flag = 1 - flag;

                // 保存本层结果

                result.add(lay);

                // 创建新的链表处理下一层的结果

                lay = new LinkedList<>();

            }

        }

        return result;

    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值