遍历是对一颗二叉树最基本的操作,有前序遍历、中序遍历、后序遍历和层次遍历四种,都可以通过递归或者数据结构实现。假定叶子结构如下:

static class leaf{
     int value;
     leaf left,right;
     leaf(int i){
         this.value = i;
     }
     public String toString() {
         return String.valueOf(value);
     }
}

1.前序遍历:先访问其根节点,再访问其左节点,最后访问其右节点。

递归实现:先访问其根节点,然后递归地去访问其左子树,左子树空后再递归地访问其右子树。

public void preOrder(leaf root) {
     if(root!=null) {
         System.out.println(root);
         preOrder(root.left);
         preOrder(root.right);
     }
}

堆栈实现:建立一个堆栈,将节点压栈。当栈不空时,弹出栈顶元素并访问,如果元素的右子树不空,则将右孩子压栈;如果元素的左子树不空,则将左儿子压栈,直到栈空为止。

public void preOrder2(leaf root) {
      if(root==null)
           return;
      Stack<leaf> stack = new Stack<leaf>();
      leaf tmp;
      stack.push(root);
      while(!stack.isEmpty()) {
           tmp = stack.pop();
           System.out.println(tmp);
           if(tmp.right!=null)
               stack.add(tmp.right);
           if(tmp.left!=null)
               stack.add(tmp.left);
      }
}

2.中序遍历:先访问其左节点,再访问其根节点,最后访问其右节点。

递归实现:从根节点出发递归地搜索左子树,直到左子树空后,访问当前节点。然后原路返回并访问之前的节点,如果右子树不为空,则再去访问其右子树。

public void inOrder(leaf root) {
      if(root!=null) {
           inOrder(root.left);
           System.out.println(root);
           inOrder(root.right);
      }
}

堆栈实现:将一个节点压栈,并沿着左子树将全部左孩子压栈,然后弹出栈顶元素并访问。如果元素存在右孩子,将其压栈并重复上面的步骤,直到栈空为止。

public void inOrder2(leaf root) {
      if(root==null)
           return;
      Stack<leaf> stack = new Stack<leaf>();
      leaf tmp = root;
      while(tmp!=null||!stack.isEmpty()) {
           while(tmp!=null) {
              stack.push(tmp);
              tmp = tmp.left;
           }
           if(!stack.isEmpty()) {
               tmp = stack.pop();
              System.out.println(tmp);
               tmp = tmp.right;
           }
      }
}

3.后序遍历:先访问其左节点,再访问其右节点,最后访问其根节点。

递归实现:从根节点出发递归地搜索其左子树,直到左子树为空,如果存在右子树,则走向右子树并继续以上步骤直至该节点左右子树都空并访问该节点,然后沿路返回并访问前面的节点。

public void afterOrder(leaf root) {
     if(root!=null) {
          afterOrder(root.left);
          afterOrder2(root.right);
          System.out.println(root);
     }
}

堆栈实现:后序遍历的难点必须先访问其左右节点,再访问其根节点。如果一个节点是叶子节点,或者其左右孩子已经被访问过了,这时就可以访问该节点。可以用额外一个节点保存之前访问过的左右孩子,用来确定当前的根节点是否可以访问。

public void afterOrder2(leaf root) {
     if(root==null)
          return;
     Stack<leaf> stack = new Stack<leaf>();
     leaf tmp1,tmp2 = null;
     stack.push(root);
     while(!stack.isEmpty()) {
          tmp1 = stack.peek();
          if((tmp1.left==null&&tmp1.right==null)||tmp2!=null&&
            (tmp2==tmp1.left||tmp2==tmp1.right)) {
                   System.out.println(tmp1);
                    stack.pop();
                    tmp2 = tmp1;
          }
          else {
               if(tmp1.right!=null)
                    stack.push(tmp1.right);
              if(tmp1.left!=null)
                    stack.push(tmp1.left);
          }
     }
}

4.层次遍历:逐层从左至右地访问每一个节点。

队列实现:创建一个队列并将根节点放进去。当队列不空时,从队列中弹出一个节点并访问,如果节点的左子树不空,将其左孩子放入队列;如果节点的右子树不空,将其右孩子放入队列。

public void levelOrder() {
     if(root==null)
          return;
     leaf p = root;
     Queue <leaf>queue = new LinkedList<leaf>();
     queue.add(p);
     leaf tmp;
     while(!queue.isEmpty()) {
          tmp = queue.poll();
          System.out.println(tmp);
          if(tmp.left!=null)
              queue.add(tmp.left);
          if(tmp.right!=null)
              queue.add(tmp.right);
     }
}

 如果你有更好的思路欢迎在评论区留言,欢迎关注点赞转发,感谢阅读。