二叉树搜索算法集合

该篇总结关于二叉树前序遍历,中序遍历,后序遍历的各种实用算法(包括递归和遍历)。

先序遍历

先序遍历又称前序遍历,先序遍历(DLR),是二叉树遍历的一种,也叫做前序周游,可记做根左右。先序遍历首先访问根结点然后遍历左子树,最后遍历右子树。

递归表达

    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> list = new ArrayList();
        helper(root,list);
        return list;
    }
    
    public void helper(TreeNode root,List<Integer> list){
        if(root==null)return;
        list.add(root.val);
        helper(root.left,list);
        helper(root.right,list);
    }

迭代表达

    public List<Integer> preorderTraversal(TreeNode root) {
        //s1
        List<Integer>  list = new ArrayList();
        Deque<TreeNode> deque = new LinkedList<TreeNode>();
        deque.add(root);
          while(!deque.isEmpty()){
            TreeNode node = deque.removeLast();
            if(node!=null){
                if(node.right==null&&node.left==null){
                    list.add(node.val);
                }else{
                    TreeNode right = node.right;
                    TreeNode left = node.left;
                    node.right = null;
                    node.left = null;
                    deque.add(right);
                    deque.add(left);
                    deque.add(node);
                }
            }
        }
        return list;
        
        //s2
        /*List<Integer>  list = new ArrayList();
        Deque<TreeNode> deque = new LinkedList<TreeNode>();
        deque.add(root);
        while(!deque.isEmpty()){
            TreeNode node = deque.removeLast();
            while(node!=null){
                list.add(node.val);
                if(node.right!=null)
                    deque.add(node.right);
                node = node.left;
            }
        }
        return list;*/
    }

s1和s2是迭代算法的两种表达方式,s1这种方式适用于前序、中序、后序三种遍历,唯一不同点是双端队列添加根节点、右节点和左节点的顺序。下面我们会看到这些变化。

 

中序遍历

中序遍历(LDR)是二叉树遍历的一种,也叫做中根遍历、中序周游。在二叉树中,中序遍历首先遍历左子树,然后访问根结点,最后遍历右子树。

递归表达

    public List<Integer> inorderTraversal(TreeNode root) {
         List<Integer> list = new ArrayList();
        helper(root,list);
        return list;
    }
    
    public void helper(TreeNode root,List<Integer> list){
        if(root==null)return;
          helper(root.left,list);
            list.add(root.val);
          helper(root.right,list);
        
    }

迭代表达

public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer>  list = new ArrayList();
        Deque<TreeNode> deque = new LinkedList<TreeNode>();
        deque.add(root);
          while(!deque.isEmpty()){
            TreeNode node = deque.removeLast();
            if(node!=null){
                if(node.right==null&&node.left==null){
                    list.add(node.val);
                }else{
                    TreeNode right = node.right;
                    TreeNode left = node.left;
                    node.right = null;
                    node.left = null;
                    deque.add(right);
                    deque.add(node);
                    deque.add(left);
                }
            }
        }
        return list;
     }

后序遍历

后序遍历(LRD)是二叉树遍历的一种,也叫做后根遍历、后序周游,可记做左右根。后序遍历有递归算法和非递归算法两种。在二叉树中,先左后右再根,即首先遍历左子树,然后遍历右子树,最后访问根结点。

递归表达

 public List<Integer> postorderTraversal(TreeNode root) {
          List<Integer> list = new ArrayList();
        helper(root,list);
        return list;
     }
      public void helper(TreeNode root,List<Integer> list){
        if(root==null)return;
          helper(root.left,list);
          helper(root.right,list);
        list.add(root.val);
       // helper(root.left,list);
        //helper(root.right,list);
    }

迭代表达

public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer>  list = new ArrayList();
        Deque<TreeNode> deque = new LinkedList<TreeNode>();
        deque.add(root);
        while(!deque.isEmpty()){
            TreeNode node = deque.removeLast();
            if(node!=null){
                if(node.right==null&&node.left==null){
                    list.add(node.val);
                }else{
                    TreeNode right = node.right;
                    TreeNode left = node.left;
                    node.right = null;
                    node.left = null;
                    deque.add(node);
                    deque.add(right);
                    deque.add(left);
                }
            }
        }
        return list;
    }

总结

可以看到三种遍历方式在代码表达上都差不多,无论递归还是迭代,只要掌握其中一种,其它两种都掌握了!!!!还是非常实用的。

点赞