二叉树的遍历

  二叉树的遍历一般分为三种遍历方法,即先序遍历、中序遍历和后序遍历。

  在中序遍历中,一个节点的前驱,是其左子树的最右下角结点,后继,是其右子树的最左下角结点。
  在后序遍历中,
  •  若结点是根结点,则其后继为空;
  •   若结点是双亲的右子树,或是左子树但双亲无右子树,则其后继为双亲结点;
  •   若结点是双亲的左子树且双亲有右子树,则其后继为右子树按后序遍历的第一个结点

 

二叉树的遍历实现如下:

  1 #include <stack>
  2 #include <queue>
  3 
  4 /*
  5 *@struct
  6 *@brief 二叉树结点
  7 */
  8 typedef struct binary_tree_node_t 
  9 {
 10   binary_tree_node_t *lchild;  /* 左孩子 */
 11   binary_tree_node_t *rchild;  /* 右孩子 */
 12   void* data; /* 结点的数据 */
 13 }binary_tree_node_t;
 14 
 15 /**
 16 * @brief 先序遍历,递归.
 17 * @param[in] root 根结点
 18 * @param[in] visit 访问数据元素的函数指针
 19 * @return 无
 20 */
 21 void pre_order_r(const binary_tree_node_t *root, int (*visit)(void*)) 
 22 {
 23   if(root != NULL)
 24   {
 25     (void)visit(root->data);
 26     pre_order_r(root->lchild, visit);
 27     pre_order_r(root->rchild, visit);
 28   }
 29 }
 30 
 31 /**
 32 * @brief 中序遍历,递归.
 33 */
 34 void in_order_r(const binary_tree_node_t *root, int (*visit)(void*)) 
 35 {
 36   if(root != NULL) 
 37   {
 38     pre_order_r(root->lchild, visit);
 39     (void)visit(root->data);
 40     pre_order_r(root->rchild, visit);
 41   }
 42 }
 43 
 44 /**
 45 * @brief 后序遍历,递归.
 46 */
 47 void post_order_r(const binary_tree_node_t *root, int (*visit)(void*)) 
 48 {
 49   if(root != NULL) 
 50   {
 51     pre_order_r(root->lchild, visit);
 52     pre_order_r(root->rchild, visit);
 53     (void)visit(root->data);
 54   }
 55 }
 56 
 57 /**
 58 * @brief 先序遍历,非递归.
 59 */
 60 void pre_order(const binary_tree_node_t *root, int (*visit)(void*)) 
 61 {
 62   const binary_tree_node_t *p;
 63   std::stack<const binary_tree_node_t *> s;
 64   p = root;
 65   if(p != NULL) 
 66   {
 67     s.push(p);
 68   }
 69 
 70   while(!s.empty()) 
 71   {
 72     p = s.top();
 73     s.pop();
 74     visit(p->data);
 75     if(p->rchild != NULL) 
 76     {
 77       s.push(p->rchild);
 78     }
 79     if(p->lchild != NULL) 
 80     {
 81       s.push(p->lchild);
 82     }
 83   }
 84 }
 85 
 86 /**
 87 * @brief 中序遍历,非递归.
 88 */
 89 void in_order(const binary_tree_node_t *root, int (*visit)(void*)) 
 90 {
 91   const binary_tree_node_t *p;
 92   std::stack<const binary_tree_node_t *> s;
 93   p = root;
 94   while(!s.empty() || p!=NULL) 
 95   {
 96     if(p != NULL) 
 97     {
 98       s.push(p);
 99       p = p->lchild;
100     } 
101     else 
102     {
103       p = s.top();
104       s.pop();
105       visit(p->data);
106       p = p->rchild;
107     }
108   }
109 }
110 
111 /**
112 * @brief 后序遍历,非递归.
113 */
114 void post_order(const binary_tree_node_t *root, int (*visit)(void*)) 
115 {
116   /* p,正在访问的结点,q,刚刚访问过的结点 */
117   const binary_tree_node_t *p, *q;
118   std::stack<const binary_tree_node_t *> s;
119   p = root;
120   do {
121     while(p != NULL) 
122     { 
123       /* 往左下走 */
124       s.push(p);
125       p = p->lchild;
126     }
127     q = NULL;
128     while(!s.empty()) 
129     {
130       p = s.top();
131       s.pop();
132       /* 右孩子不存在或已被访问,访问之 */
133       if(p->rchild == q) 
134       {
135         visit(p->data);
136         q = p; /* 保存刚访问过的结点 */
137       } 
138       else 
139       {
140         /* 当前结点不能访问,需第二次进栈 */
141         s.push(p);
142         /* 先处理右子树 */
143         p = p->rchild;
144         break;
145       }
146     }
147   }while(!s.empty());
148 }
149 
150 /**
151 * @brief 层次遍历,也即 BFS.
152 *
153 * 跟先序遍历一模一样,唯一的不同是栈换成了队列
154 */
155 void level_order(const binary_tree_node_t *root, int (*visit)(void*)) 
156 {
157   const binary_tree_node_t *p;
158   std::queue<const binary_tree_node_t *> q;
159   p = root;
160   if(p != NULL) 
161   {
162     q.push(p);
163   }
164   while(!q.empty()) 
165   {
166     p = q.front();
167     q.pop();
168     visit(p->data);
169     if(p->lchild != NULL) 
170     {
171       /* 先左后右或先右后左无所谓 */
172       q.push(p->lchild);
173     }
174     if(p->rchild != NULL) 
175     {
176       q.push(p->rchild);
177     }
178   }
179 }

 

posted @ 2015-03-18 14:36  简简单单-平平淡淡  阅读(270)  评论(0编辑  收藏  举报