码迷,mamicode.com
首页 > 其他好文 > 详细

二叉树的非递归遍历

时间:2014-11-15 22:59:23      阅读:485      评论:0      收藏:0      [点我收藏+]

标签:des   style   blog   http   io   color   ar   os   sp   

二叉树的前序非递归遍历:

 前序遍历的顺序:根结点——左孩子——右孩子“。

根据前序遍历访问结点的顺序可知:优先访问根结点,然后再分别访问左孩子和右孩子。

对于任意结点来说,都可将其视为根结点,因此可直接访问,访问完之后,若其左孩子不为空,则按照相同规则访问左子树;当访问了左子树之后,再访问它的右子树。

其处理过程如下:

对于任一结点 P:
1)若P结点不为空,则将其入栈并且访问该结点,然后将其左孩子置为下个要访问的结点。执行步骤1);
2)若P结点为空,则取出栈顶元素,并将其右孩子置为下个要访问的结点,然后循环执行1)。
3)直到P为空,并且栈也为空是,退出循环,即遍历结束。

代码如下:

bubuko.com,布布扣
 1 void PreTraversal_Non_Recursive(pBTree T) // 前序非递归遍历
 2 {
 3     if( T == NULL)
 4         return;    
 5     
 6     stack<pBTree> st;
 7 
 8     pBTree p = T;
 9     while( p!= NULL || !st.empty())
10     {
11         while( p != NULL) //p不为空时
12         {
13             cout << p->data_ <<" "; //访问p结点
14             st.push(p); //压入栈中
15             p = p->left_; //访问其左子树
16         }
17         
18         if( !st.empty() )
19         {
20             p = st.top();
21             st.pop(); //弹出
22             p = p->right_;
23         }
24     }
25 }
View Code

二叉树的中序非递归遍历:

中序遍历的顺序:”左孩子——根结点——右孩子“;

中序遍历过程和前序类似,其处理过程如下:

对于任一结点 P:
1)若P结点不为空,则将其入栈,然后将其左孩子置为下个要访问的结点。执行步骤1);
2)若P结点为空,则取出栈顶元素并且访问该结点,并将其右孩子置为下个要访问的结点,然后循环执行1)。
3)直到P为空,并且栈也为空是,退出循环,即遍历结束。

代码如下:

bubuko.com,布布扣
 1 void InOrder_Traversal_Non_Recursive(pBTree T) //终须遍历(非递归)
 2 {
 3     if( T == NULL)
 4         return;    
 5 
 6     stack<pBTree> st;
 7     pBTree p = T;
 8 
 9     while( p != NULL || !st.empty())
10     {
11         while( p != NULL)
12         {
13             st.push(p);
14             p = p->left_;
15         }
16 
17         if( !st.empty())
18         {
19             p = st.top();
20             cout << p->data_ << " ";
21             st.pop();
22             p = p->right_;
23         }
24     }
25 }
View Code

二叉树的后序非递归遍历:

前序遍历的顺序:左孩子——右孩子——根结点“。

后续遍历较为麻烦,因为后续非递归遍历二叉树的顺序是先访问左子树,再访问右子树,最后访问其根结点,当用栈来存储结点是,必须分清返回根结点时,是从左子树返回的,还是从右子树返回的。

思路如下:要保证根结点在左孩子和右孩子访问之后才能访问,因此对于任意结点,先将其入栈。

1)如果P不存在左孩子和右孩子,则可以直接访问它;

2)P存在左孩子或者右孩子,但是左孩子或者右孩子都已经被访问过了,则同样可以直接访问该结点。

3)除此之外,即存在左孩子或者右孩子并且还都没有访问,这时,我们先将其右孩子入栈,然后将左孩子入栈,这样我们就保证了每次取出站定元素的时候,左孩子在右孩子前面  被访问。并且也能保证左孩子或者右孩子能在根结点之前访问。

代码如下:

bubuko.com,布布扣
 1 void PostOrder_Traversal_Non_Recursive(pBTree T) //非递归后序遍历
 2 {
 3     if( T == NULL)
 4         return;
 5 
 6     pBTree cur; //当前访问的结点
 7     pBTree pre = NULL; //前一次访问的结点
 8     stack<pBTree> st;
 9     st.push(T);
10 
11     while( !st.empty())
12     {
13         cur = st.top();
14 
15         //当前结点没有孩子结点 或者 当前结点的左孩子或者右孩子已经被访问过 
16         if( (cur->left_ == NULL && cur->right_==NULL) || 
17             ( pre!= NULL &&(pre ==cur->left_ || pre == cur->right_) ) )
18         {
19             cout << cur->data_ <<" ";
20             st.pop();
21             pre = cur;
22         }
23         else
24         {
25             if( cur->right_ != NULL)
26                 st.push(cur->right_);
27             if( cur->left_  != NULL)
28                 st.push(cur->left_);
29         }
30     }
31 }
View Code

全部实现代码如下:

bubuko.com,布布扣
  1 #include <iostream>
  2 #include <string>
  3 #include <stack>
  4 #include <assert.h>
  5 #include <stdlib.h>
  6 #include <time.h>
  7 using namespace std;
  8 const int N =10;
  9 
 10 typedef struct node //二叉树的数据结构
 11 {
 12     int data_;
 13     struct node* left_;
 14     struct node* right_;
 15 }BTree, *pBTree;
 16 
 17 void  Create_Btree_with_arr(pBTree &T, int *arr, int begin, int end)//len俄日数组的长度,也是树的结点数
 18 {
 19     if(begin > end)
 20         return;
 21 
 22     int mid = (begin + end)/2;
 23     if( T == NULL)
 24     {
 25         T =new BTree; //申请空间
 26         arr[mid] = rand()%100;
 27         cout<< arr[mid] <<" ";
 28         T->data_ = arr[mid]; //数值随机化
 29         T->left_ = NULL;
 30         T->right_ = NULL;
 31     }
 32     Create_Btree_with_arr(T->left_, arr, begin, mid-1);//左边(不包括T)
 33     Create_Btree_with_arr(T->right_, arr, mid+1, end); //右边(不包括T)
 34 }
 35 
 36 void PreTraversal_Non_Recursive(pBTree T) // 前序非递归遍历
 37 {
 38     if( T == NULL)
 39         return;    
 40     
 41     stack<pBTree> st;
 42 
 43     pBTree p = T;
 44     while( p!= NULL || !st.empty())
 45     {
 46         while( p != NULL) //p不为空时
 47         {
 48             cout << p->data_ <<" "; //访问p结点
 49             st.push(p); //压入栈中
 50             p = p->left_; //访问其左子树
 51         }
 52         
 53         if( !st.empty() )
 54         {
 55             p = st.top();
 56             st.pop(); //弹出
 57             p = p->right_;
 58         }
 59     }
 60 }
 61 
 62 void InOrder_Traversal_Non_Recursive(pBTree T) //终须遍历(非递归)
 63 {
 64     if( T == NULL)
 65         return;    
 66 
 67     stack<pBTree> st;
 68     pBTree p = T;
 69 
 70     while( p != NULL || !st.empty())
 71     {
 72         while( p != NULL)
 73         {
 74             st.push(p);
 75             p = p->left_;
 76         }
 77 
 78         if( !st.empty())
 79         {
 80             p = st.top();
 81             cout << p->data_ << " ";
 82             st.pop();
 83             p = p->right_;
 84         }
 85     }
 86 }
 87 
 88 void PostOrder_Traversal_Non_Recursive(pBTree T) //非递归后序遍历
 89 {
 90     if( T == NULL)
 91         return;
 92 
 93     pBTree cur; //当前访问的结点
 94     pBTree pre = NULL; //前一次访问的结点
 95     stack<pBTree> st;
 96     st.push(T);
 97 
 98     while( !st.empty())
 99     {
100         cur = st.top();
101 
102         //当前结点没有孩子结点 或者 当前结点的左孩子或者右孩子已经被访问过 
103         if( (cur->left_ == NULL && cur->right_==NULL) || 
104             ( pre!= NULL &&(pre ==cur->left_ || pre == cur->right_) ) )
105         {
106             cout << cur->data_ <<" ";
107             st.pop();
108             pre = cur;
109         }
110         else
111         {
112             if( cur->right_ != NULL)
113                 st.push(cur->right_);
114             if( cur->left_  != NULL)
115                 st.push(cur->left_);
116         }
117     }
118 }
119 
120 void DestructBTree( pBTree &T) //二叉树的销毁
121 {
122     if( T == NULL)
123         return;
124 
125     DestructBTree( T->left_);
126     DestructBTree( T->right_);
127     delete T; //free之后的指针成为了野指针,内容并不为空
128     T = NULL;//置空
129 }
130 
131 int main(int argc, char const *argv[])
132 {
133     srand(time(NULL));
134     int arr[N]= {0};
135 
136     pBTree T =NULL;
137     Create_Btree_with_arr(T, arr, 0,N-1);
138     cout << endl;
139 
140     PreTraversal_Non_Recursive(T);
141     cout << endl;
142 
143     InOrder_Traversal_Non_Recursive(T);
144     cout << endl;
145 
146     PostOrder_Traversal_Non_Recursive(T);
147     cout << endl;
148 
149     DestructBTree(T);
150     cout <<"Free Over" << endl;
151     assert( T == NULL); //验证 T 是否真的被释放
152     return 0;
153 }
View Code

完毕。 

二叉树的非递归遍历

标签:des   style   blog   http   io   color   ar   os   sp   

原文地址:http://www.cnblogs.com/xfxu/p/4100260.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!