二叉树的遍历

本文主要就二叉树的遍历方式进行总结和记录,从而了解递归、栈以及队列的应用,通常对于一个二叉树的遍历方式大致分为:

  1. 前序遍历(中 -> 左 -> 右)
  2. 中序遍历(左 -> 中 -> 右)
  3. 后续遍历(左 -> 右 -> 中)
  4. 层次遍历
  • 前序遍历

    • 递归实现

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      /*
      * 思路:若二叉树非空:
      * 1、访问根节点
      * 2、遍历左子树
      * 3、遍历右子数
      */
      public void PreOrder(Btree T){
      if(T != null){
      show(T)
      PreOrder(T.left)
      PreOrder(T.right)
      }
      }
  • 栈实现

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    /*
    * 思路:若二叉树非空
    * 1、根遍历,拿到一个节点的指针,先判断是否为空,不为空就先访问该结点,然后直接进栈,
    * 2、接着遍历左子树;为空则要从栈中弹出一个节点来,这个时候弹出的结点就是其父亲
    * 3、然后访问其父亲的右子树,直到当前节点为空且栈为空时,算法结束.
    *
    */
    public void PreOrder1(Btree T) {
    stack<Btree> st;
    if (T == NULL){
    return null;
    }
    st.push(T);
    while (!st.empty()){
    Btree T =st.pop();
    show(T)
    if (T.right!=NULL)
    st.push(p.right);
    if (p.left!=NULL)
    st.push(p.left);
    }
    return null;
    }
  • 中序遍历

    • 递归实现

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      /*
      * 思路:若二叉树非空:
      * 1、遍历左子树
      * 2、访问根节点
      * 3、遍历右子数
      */
      public void MidOrder(Btree T){
      if(T != null){
      MidOrder(T.left)
      show(T)
      MidOrder(T.right)
      }
      }
  • 栈实现

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    /*
    * 思路:借助栈
    * 1、初始时依次扫描根节点的所在左侧节点并将它们一一进栈;
    * 2、出栈一个节点,访问它
    * 3、扫描该节点的右孩子节点并将其出栈
    * 4、依次扫描右孩子节点的所有左侧节点并一一进栈
    * 5、反复 2 - 4 步骤
    */
    public void MidOrder2(Btree T){
    Stack s = new Stack();
    BTree p = T;
    while(p||!s.IsEmpty()){
    if(p){
    s.push(p);
    p = p.left;
    }else{
    p = s.pop();
    show(p);
    p = p.right;
    }
    }
    }
  • 后序遍历

    • 递归实现

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      /*
      * 思路:若二叉树非空:
      * 1、遍历左子树
      * 2、遍历右子数
      * 3、访问根节点
      */
      public void PostOrder(Btree T){
      if(T != null){
      PostOrder(T.left)
      PostOrder(T.right)
      show(T)
      }
      }
  • 栈实现

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    /*
    * 思路:借助栈
    */
    public void AfterOrder2(Btree root){
    if (root == NULL){
    return;
    }
    Stack<BTree> s = new Stack();
    s.push(root);//根指针入栈
    while (!s.empty())
    {
    //重复将栈顶指针指向结点的左子树压栈,直到栈顶指针指向结点的左子树为空
    while (s.top().left != NULL){
    s.push(s.top().left);
    }
    Btree last = NULL;//上一次遍历过的指针
    //重复检查
    while (!s.empty()){
    if (s.top().right==NULL||last==s.top().right) {
    //如果栈顶指针指向结点的右子树为空或者遍历过
    show(s.top())
    last = s.top();//更新指针last
    s.pop();//栈顶指针出栈
    }
    //如果栈顶指针指向的结点的右子树不为空
    else if(s.top()->R!=NULL){
    s.push(s.top()->R);//将右子树入栈
    break;//退出检查
    }
    }
    }
    }
  • 层次遍历

  • 队列实现

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    /*
    * 思路:借助队列 队列的就是FIFO
    * 1、初始将根节点入队并访问根节点,然后出队
    * 2、如果有左子树,将左子树的根入队
    * 3、如果有右子树,将右子树的根入队
    * 4、然后出队,访问该节点
    * 5、反复出队访问直到队列为空
    * 伪代码
    */
    public void levelOrder(Btree T){
    InitQueue(Q)
    BTree p;
    EnQueue(Q,T)
    while(!IsEmpty(Q)){
    Dequeue(Q,p);
    show(p);
    if(p.left != null){
    EnQueue(Q,p.left);
    }
    if(p.right != null){
    Enqueue(Q,p.right);
    }
    }
    }
  • 总结

    二叉树是数据结构中非常重要的一环,弄懂其相关操作对于后续的学习也是十分重要,Java中的Treemap以及Hashmap中都有红黑树的引入,红黑树就是二叉树的一种特殊存在,通常我们也叫它黑高平衡树,后面再详细描述~