歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> 二叉樹的遍歷

二叉樹的遍歷

日期:2017/3/1 9:30:47   编辑:Linux編程

二叉樹的遍歷一般分為三種遍歷方法,即先序遍歷、中序遍歷和後序遍歷。在中序遍歷中,一個節點的前驅,是其左子樹的最右下角結點,後繼,是其右子樹的最左下角結點。

  在後序遍歷中,

  •  若結點是根結點,則其後繼為空;

  •   若結點是雙親的右子樹,或是左子樹但雙親無右子樹,則其後繼為雙親結點;

  •   若結點是雙親的左子樹且雙親有右子樹,則其後繼為右子樹按後序遍歷的第一個結點

二叉樹的遍歷實現如下:

#include <stack>
#include <queue>

/*
*@struct
*@brief 二叉樹結點
*/
typedef struct binary_tree_node_t
{
  binary_tree_node_t *lchild;  /* 左孩子 */
  binary_tree_node_t *rchild;  /* 右孩子 */
  void* data; /* 結點的數據 */
}binary_tree_node_t;

/**
* @brief 先序遍歷,遞歸.
* @param[in] root 根結點
* @param[in] visit 訪問數據元素的函數指針
* @return 無
*/
void pre_order_r(const binary_tree_node_t *root, int (*visit)(void*))
{
  if(root != NULL)
  {
    (void)visit(root->data);
    pre_order_r(root->lchild, visit);
    pre_order_r(root->rchild, visit);
  }
}

/**
* @brief 中序遍歷,遞歸.
*/
void in_order_r(const binary_tree_node_t *root, int (*visit)(void*))
{
  if(root != NULL)
  {
    pre_order_r(root->lchild, visit);
    (void)visit(root->data);
    pre_order_r(root->rchild, visit);
  }
}

/**
* @brief 後序遍歷,遞歸.
*/
void post_order_r(const binary_tree_node_t *root, int (*visit)(void*))
{
  if(root != NULL)
  {
    pre_order_r(root->lchild, visit);
    pre_order_r(root->rchild, visit);
    (void)visit(root->data);
  }
}

/**
* @brief 先序遍歷,非遞歸.
*/
void pre_order(const binary_tree_node_t *root, int (*visit)(void*))
{
  const binary_tree_node_t *p;
  std::stack<const binary_tree_node_t *> s;
  p = root;
  if(p != NULL)
  {
    s.push(p);
  }

  while(!s.empty())
  {
    p = s.top();
    s.pop();
    visit(p->data);
    if(p->rchild != NULL)
    {
      s.push(p->rchild);
    }
    if(p->lchild != NULL)
    {
      s.push(p->lchild);
    }
  }
}

/**
* @brief 中序遍歷,非遞歸.
*/
void in_order(const binary_tree_node_t *root, int (*visit)(void*))
{
  const binary_tree_node_t *p;
  std::stack<const binary_tree_node_t *> s;
  p = root;
  while(!s.empty() || p!=NULL)
  {
    if(p != NULL)
    {
      s.push(p);
      p = p->lchild;
    }
    else
    {
      p = s.top();
      s.pop();
      visit(p->data);
      p = p->rchild;
    }
  }
}

/**
* @brief 後序遍歷,非遞歸.
*/
void post_order(const binary_tree_node_t *root, int (*visit)(void*))
{
  /* p,正在訪問的結點,q,剛剛訪問過的結點 */
  const binary_tree_node_t *p, *q;
  std::stack<const binary_tree_node_t *> s;
  p = root;
  do {
    while(p != NULL)
    {
      /* 往左下走 */
      s.push(p);
      p = p->lchild;
    }
    q = NULL;
    while(!s.empty())
    {
      p = s.top();
      s.pop();
      /* 右孩子不存在或已被訪問,訪問之 */
      if(p->rchild == q)
      {
        visit(p->data);
        q = p; /* 保存剛訪問過的結點 */
      }
      else
      {
        /* 當前結點不能訪問,需第二次進棧 */
        s.push(p);
        /* 先處理右子樹 */
        p = p->rchild;
        break;
      }
    }
  }while(!s.empty());
}

/**
* @brief 層次遍歷,也即 BFS.
*
* 跟先序遍歷一模一樣,唯一的不同是棧換成了隊列
*/
void level_order(const binary_tree_node_t *root, int (*visit)(void*))
{
  const binary_tree_node_t *p;
  std::queue<const binary_tree_node_t *> q;
  p = root;
  if(p != NULL)
  {
    q.push(p);
  }
  while(!q.empty())
  {
    p = q.front();
    q.pop();
    visit(p->data);
    if(p->lchild != NULL)
    {
      /* 先左後右或先右後左無所謂 */
      q.push(p->lchild);
    }
    if(p->rchild != NULL)
    {
      q.push(p->rchild);
    }
  }
}

二叉樹的常見問題及其解決程序 http://www.linuxidc.com/Linux/2013-04/83661.htm

【遞歸】二叉樹的先序建立及遍歷 http://www.linuxidc.com/Linux/2012-12/75608.htm

在JAVA中實現的二叉樹結構 http://www.linuxidc.com/Linux/2008-12/17690.htm

【非遞歸】二叉樹的建立及遍歷 http://www.linuxidc.com/Linux/2012-12/75607.htm

二叉樹遞歸實現與二重指針 http://www.linuxidc.com/Linux/2013-07/87373.htm

二叉樹先序中序非遞歸算法 http://www.linuxidc.com/Linux/2014-06/102935.htm

輕松搞定面試中的二叉樹題目 http://www.linuxidc.com/linux/2014-07/104857.htm

Copyright © Linux教程網 All Rights Reserved