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

二叉树方面的问题

时间:2016-04-22 16:32:59      阅读:249      评论:0      收藏:0      [点我收藏+]

标签:

  1 #include <iostream>
  2 #include <stdio.h>
  3 #include <string>
  4 #include <string.h>
  5 #include <algorithm>
  6 #include <vector>
  7 #include <map>
  8 #include <stack>
  9 #define maxn 110
 10 #define inf 0x7fffffff
 11 using namespace std;
 12 int num, pos;
 13 struct BTNode
 14 {
 15     int data;
 16     BTNode* lchild;
 17     BTNode* rchild;
 18 };
 19 // 二叉排序树插入节点
 20 void InsertBTNode(BTNode*& root, int k)
 21 {
 22     if(NULL == root)
 23     {
 24         root = (BTNode*)malloc(sizeof(BTNode));
 25         root->data = k;
 26         root->lchild = NULL;
 27         root->rchild = NULL;
 28     }
 29     else
 30     {
 31         if(k < root->data)InsertBTNode(root->lchild, k);
 32         else InsertBTNode(root->rchild, k);
 33     }
 34 }
 35 // 递归先序遍历
 36 void PreOrderTraverse(BTNode* root)
 37 {
 38     if(NULL != root)
 39     {
 40         printf("%d ", root->data);
 41         PreOrderTraverse(root->lchild);
 42         PreOrderTraverse(root->rchild);
 43     }
 44 
 45 }
 46 // 递归中序遍历
 47 void MidOrderTraverse(BTNode* root)
 48 {
 49     if(NULL != root)
 50     {
 51         MidOrderTraverse(root->lchild);
 52         printf("%d ", root->data);
 53         MidOrderTraverse(root->rchild);
 54     }
 55 }
 56 // 递归后续遍历
 57 void LastOrderTraverse(BTNode* root)
 58 {
 59     if(NULL != root)
 60     {
 61         LastOrderTraverse(root->lchild);
 62         LastOrderTraverse(root->rchild);
 63         printf("%d ", root->data);
 64     }
 65 }
 66 
 67 struct StackNode
 68 {
 69     BTNode* pBTNode;
 70     bool left;
 71     bool right;
 72     StackNode(){}
 73     StackNode(BTNode* x, bool y, bool z)
 74     {
 75         pBTNode = x;
 76         left = y;
 77         right = z;
 78     }
 79 };
 80 /*
 81 非递归遍历,对于任意一个节点(叶子节点也一样)都有左右两边是否访问过的属性,
 82 根据左右边是否被访问过,按照顺序实现前中后序的遍历,然后在判断是否有左右孩子,
 83 ,如,非递归先序遍历, 节点在入站前, 先输出,然后看左边是否访问过,没有的话,在看
 84 是否有左孩子,有左孩子的话,就输出左孩子的值,把左孩子加入栈中(左孩子的左右两边是没有被访问过的);
 85 ,当发现左边被访问过了,再看右边是否访问过,没有的话,是否有右孩子....;若左右都访问过了,则出栈。
 86 */
 87 // 非递归先序
 88 void Pre_NoRecurTraverse(BTNode* root)
 89 {
 90     if(NULL ==  root)return ;
 91     stack<StackNode>my_stack;
 92     printf("%d ", root->data);
 93     my_stack.push(StackNode(root, true, true));
 94     while(!my_stack.empty())
 95     {
 96         StackNode p = my_stack.top();
 97         if(true == p.left)
 98         {
 99             p.left = false;
100             my_stack.pop();
101             my_stack.push(p);
102             if(NULL != p.pBTNode->lchild)
103             {
104                 printf("%d ", p.pBTNode->lchild->data);
105                 my_stack.push(StackNode(p.pBTNode->lchild, true, true));
106             }
107         }
108         else
109         {
110             if(true == p.right)
111             {
112                 p.right = false;
113                 my_stack.pop();
114                 my_stack.push(p);
115                 if(NULL != p.pBTNode->rchild)
116                 {
117                     printf("%d ", p.pBTNode->rchild->data);
118                     my_stack.push(StackNode(p.pBTNode->rchild, true, true));
119                 }
120             }
121             else
122                 my_stack.pop();
123         }
124     }
125 }
126 // 非递归中序
127 void Mid_NoRecurTraverse(BTNode* root)
128 {
129     if(NULL == root)return ;
130     stack<StackNode>my_stack;
131     my_stack.push(StackNode(root, true, true));
132     while(!my_stack.empty())
133     {
134         StackNode p = my_stack.top();
135         if(true == p.left)
136         {
137             p.left = false;
138             my_stack.pop();
139             my_stack.push(p);
140             if(NULL != p.pBTNode->lchild)
141             {
142                 my_stack.push(StackNode(p.pBTNode->lchild, true,true));
143             }
144         }
145         else
146         {
147             if(true == p.right)
148             {
149                 printf("%d ", p.pBTNode->data);
150                 p.right = false;
151                 my_stack.pop();
152                 my_stack.push(p);
153                 if(NULL != p.pBTNode->rchild)
154                 {
155                     my_stack.push(StackNode(p.pBTNode->rchild, true, true));
156                 }
157             }
158             else
159                 my_stack.pop();
160         }
161 
162     }
163 }
164 // 非递归后序
165 void Last_NoRecurTraverse(BTNode* root)
166 {
167     if(NULL ==  root)return;
168     stack<StackNode>my_stack;
169     my_stack.push(StackNode(root, true, true));
170     while(!my_stack.empty())
171     {
172         StackNode p = my_stack.top();
173         if(true == p.left)
174         {
175             p.left = false;
176             my_stack.pop();
177             my_stack.push(p);
178             if(NULL!=p.pBTNode->lchild)
179                 my_stack.push(StackNode(p.pBTNode->lchild, true, true));
180 
181         }
182         else
183         {
184             if(true == p.right)
185             {
186                 p.right = false;
187                 my_stack.pop();
188                 my_stack.push(p);
189                 if(NULL != p.pBTNode->rchild)
190                     my_stack.push(StackNode(p.pBTNode->rchild, true, true));
191             }
192             else
193             {
194                 printf("%d ", p.pBTNode->data);
195                 my_stack.pop();
196             }
197         }
198     }
199 }
200 // 根据先序和中序建树
201 BTNode* ConsrtcutTree(int pre[], int preL, int preR, int mid[], int midL, int midR)
202 {
203     BTNode* root = (BTNode*)malloc(sizeof(BTNode));
204     root->data = pre[preL];
205     root->lchild = root->rchild = NULL;
206     if(preL == preR)return root;
207     int k = pre[preL];
208     int num = 0;
209     int pos = midL;
210     while(mid[pos]!=k)
211     {
212         num++;
213         pos++;
214     }
215     if(pos > midL)root->lchild = ConsrtcutTree(pre, preL+1, preL+num, mid, midL, pos - 1);
216     if(pos < midR)root->rchild = ConsrtcutTree(pre, preL+num+1, preR, mid, pos+1, midR);
217 
218     return root;
219 
220 }
221 int main()
264 {
265     /*数据

            7
            7 4 9 5 9 6 8
            7
            7 4 5 6 9 9 8
            4 5 6 7 8 9 9

 


   */ 266 //freopen("data.txt", "r", stdin); 267 BTNode* root = NULL; 268 int n,a; 269 scanf("%d", &n); 270 for(int i = 0; i < n;++i) 271 { 272 scanf("%d", &a); 273 InsertBTNode(root, a); 274 } 275 printf("\n先序遍历:\n"); 276 PreOrderTraverse(root); 277 printf("\n中序遍历:\n"); 278 MidOrderTraverse(root); 279 printf("\n后序遍历:\n"); 280 LastOrderTraverse(root); 281 printf("\n非递归先序遍历:\n"); 282 Pre_NoRecurTraverse(root); 283 284 printf("\n非递归中序遍历:\n"); 285 Mid_NoRecurTraverse(root); 286 287 printf("\n非递归后序遍历:\n"); 288 Last_NoRecurTraverse(root); 289 290 291 printf("根据先序和中序建树:\n"); 292 scanf("%d", &n); 293 printf("输入先序:\n"); 294 int pre[maxn]; 295 int mid[maxn]; 296 for(int i = 0 ; i < n;++i) 297 scanf("%d", &pre[i]); 298 printf("输入中序:\n"); 299 for(int i = 0 ; i < n;++i) 300 scanf("%d", &mid[i]); 301 BTNode* head = NULL; 302 head = ConsrtcutTree(pre, 0, n-1, mid, 0, n-1); 303 304 printf("\n先序遍历:\n"); 305 PreOrderTraverse(head); 306 307 printf("\n将树序列化树:\n"); 308 char str[maxn]; 309 num = 0; 310 PreLinearTree(root, str); 311 312 printf("\n将序列化变为树:\n"); 313 BTNode* p = NULL; 314 pos = 0; 315 p = ReverseLinearTree(str); 316 printf("\n先序遍历:\n"); 317 PreOrderTraverse(p); 318 319 320 321 322 }

序列化的意思是将内存中的一些特定的结构,变成有格式信息的字符串。如,对于链表而言,我们可以将1->2->3->NULL这样的链表序列化为"1,2,3"。对于序列化算法,必须支持反序列化,及在约定的格式下,可以将满足格式要求的字符串重新构造为想要的结构。

我们采用的是先序遍历实现序列话,为什么采用先序遍历,因为先序的话,是先找到的根,而中序和后序不是,这样反序列话时机不方便

为了能够在重构二叉树时结点能够插入到正确的位置,在使用先序遍历保存二叉树到文件中的时候需要把NULL结点也保存起来(可以使用特殊符号如“#”来标识NULL结点)。

假定二叉树如下所示:

 

    _30_
   /    \   
  10    20
 /     /  50    45  35

 

则使用先序遍历,保存到文件中的内容如下:

 

30 10 50 # # # 20 45 # # 35 # #

序列化代码:
技术分享
 1 void PreLinearTree(BTNode* root, char str[])
 2 {
 3     if(NULL == root)
 4     {
 5         printf("# ");
 6         str[num++] = #;
 7         return;
 8     }
 9     else
10     {
11         printf("%d ", root->data);
12         str[num++] = 0 + root->data;
13         PreLinearTree(root->lchild, str);
14         PreLinearTree(root->rchild, str);
15     }
16 
17 }
View Code

反序列化:

用先序遍历的思想每次读取一个结点,如果读取到NULL结点的标识符号“#”,则忽略它。如果读取到结点数值,则插入到当前结点,然后遍历左孩子和右孩子。

技术分享
 1 BTNode* ReverseLinearTree(char str[])
 2 {
 3     if(# == str[pos])
 4     {
 5         ++pos;// 这个地方容易忘
 6         return NULL;
 7     }
 8     else
 9     {
10         BTNode* root = NULL;
11         root  = (BTNode* )malloc(sizeof(BTNode));
12         root->data = str[pos] - 0;
13         ++pos;
14         root->lchild = ReverseLinearTree(str);
15         root->rchild = ReverseLinearTree(str);
16         return root;
17     }
18     
19 }
View Code

当然也可以采用层次遍历的方法来实现序列化,原理是和上面一样的

二叉树方面的问题

标签:

原文地址:http://www.cnblogs.com/acSzz/p/5421386.html

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