二叉树方面的问题

 
  1   1 #include <iostream>
  2   2 #include <stdio.h>
  3   3 #include <string>
  4   4 #include <string.h>
  5   5 #include <algorithm>
  6   6 #include <vector>
  7   7 #include <map>
  8   8 #include <stack>
  9   9 #define maxn 110
 10  10 #define inf 0x7fffffff
 11  11 using namespace std;
 12  12 int num, pos;
 13  13 struct BTNode
 14  14 {
 15  15     int data;
 16  16     BTNode* lchild;
 17  17     BTNode* rchild;
 18  18 };
 19  19 // 二叉排序树插入节点
 20  20 void InsertBTNode(BTNode*& root, int k)
 21  21 {
 22  22     if(NULL == root)
 23  23     {
 24  24         root = (BTNode*)malloc(sizeof(BTNode));
 25  25         root->data = k;
 26  26         root->lchild = NULL;
 27  27         root->rchild = NULL;
 28  28     }
 29  29     else
 30  30     {
 31  31         if(k < root->data)InsertBTNode(root->lchild, k);
 32  32         else InsertBTNode(root->rchild, k);
 33  33     }
 34  34 }
 35  35 // 递归先序遍历
 36  36 void PreOrderTraverse(BTNode* root)
 37  37 {
 38  38     if(NULL != root)
 39  39     {
 40  40         printf("%d ", root->data);
 41  41         PreOrderTraverse(root->lchild);
 42  42         PreOrderTraverse(root->rchild);
 43  43     }
 44  44 
 45  45 }
 46  46 // 递归中序遍历
 47  47 void MidOrderTraverse(BTNode* root)
 48  48 {
 49  49     if(NULL != root)
 50  50     {
 51  51         MidOrderTraverse(root->lchild);
 52  52         printf("%d ", root->data);
 53  53         MidOrderTraverse(root->rchild);
 54  54     }
 55  55 }
 56  56 // 递归后续遍历
 57  57 void LastOrderTraverse(BTNode* root)
 58  58 {
 59  59     if(NULL != root)
 60  60     {
 61  61         LastOrderTraverse(root->lchild);
 62  62         LastOrderTraverse(root->rchild);
 63  63         printf("%d ", root->data);
 64  64     }
 65  65 }
 66  66 
 67  67 struct StackNode
 68  68 {
 69  69     BTNode* pBTNode;
 70  70     bool left;
 71  71     bool right;
 72  72     StackNode(){}
 73  73     StackNode(BTNode* x, bool y, bool z)
 74  74     {
 75  75         pBTNode = x;
 76  76         left = y;
 77  77         right = z;
 78  78     }
 79  79 };
 80  80 /*
 81  81 非递归遍历,对于任意一个节点(叶子节点也一样)都有左右两边是否访问过的属性,
 82  82 根据左右边是否被访问过,按照顺序实现前中后序的遍历,然后在判断是否有左右孩子,
 83  83 ,如,非递归先序遍历, 节点在入站前, 先输出,然后看左边是否访问过,没有的话,在看
 84  84 是否有左孩子,有左孩子的话,就输出左孩子的值,把左孩子加入栈中(左孩子的左右两边是没有被访问过的);
 85  85 ,当发现左边被访问过了,再看右边是否访问过,没有的话,是否有右孩子....;若左右都访问过了,则出栈。
 86  86 */
 87  87 // 非递归先序
 88  88 void Pre_NoRecurTraverse(BTNode* root)
 89  89 {
 90  90     if(NULL ==  root)return ;
 91  91     stack<StackNode>my_stack;
 92  92     printf("%d ", root->data);
 93  93     my_stack.push(StackNode(root, true, true));
 94  94     while(!my_stack.empty())
 95  95     {
 96  96         StackNode p = my_stack.top();
 97  97         if(true == p.left)
 98  98         {
 99  99             p.left = false;
100 100             my_stack.pop();
101 101             my_stack.push(p);
102 102             if(NULL != p.pBTNode->lchild)
103 103             {
104 104                 printf("%d ", p.pBTNode->lchild->data);
105 105                 my_stack.push(StackNode(p.pBTNode->lchild, true, true));
106 106             }
107 107         }
108 108         else
109 109         {
110 110             if(true == p.right)
111 111             {
112 112                 p.right = false;
113 113                 my_stack.pop();
114 114                 my_stack.push(p);
115 115                 if(NULL != p.pBTNode->rchild)
116 116                 {
117 117                     printf("%d ", p.pBTNode->rchild->data);
118 118                     my_stack.push(StackNode(p.pBTNode->rchild, true, true));
119 119                 }
120 120             }
121 121             else
122 122                 my_stack.pop();
123 123         }
124 124     }
125 125 }
126 126 // 非递归中序
127 127 void Mid_NoRecurTraverse(BTNode* root)
128 128 {
129 129     if(NULL == root)return ;
130 130     stack<StackNode>my_stack;
131 131     my_stack.push(StackNode(root, true, true));
132 132     while(!my_stack.empty())
133 133     {
134 134         StackNode p = my_stack.top();
135 135         if(true == p.left)
136 136         {
137 137             p.left = false;
138 138             my_stack.pop();
139 139             my_stack.push(p);
140 140             if(NULL != p.pBTNode->lchild)
141 141             {
142 142                 my_stack.push(StackNode(p.pBTNode->lchild, true,true));
143 143             }
144 144         }
145 145         else
146 146         {
147 147             if(true == p.right)
148 148             {
149 149                 printf("%d ", p.pBTNode->data);
150 150                 p.right = false;
151 151                 my_stack.pop();
152 152                 my_stack.push(p);
153 153                 if(NULL != p.pBTNode->rchild)
154 154                 {
155 155                     my_stack.push(StackNode(p.pBTNode->rchild, true, true));
156 156                 }
157 157             }
158 158             else
159 159                 my_stack.pop();
160 160         }
161 161 
162 162     }
163 163 }
164 164 // 非递归后序
165 165 void Last_NoRecurTraverse(BTNode* root)
166 166 {
167 167     if(NULL ==  root)return;
168 168     stack<StackNode>my_stack;
169 169     my_stack.push(StackNode(root, true, true));
170 170     while(!my_stack.empty())
171 171     {
172 172         StackNode p = my_stack.top();
173 173         if(true == p.left)
174 174         {
175 175             p.left = false;
176 176             my_stack.pop();
177 177             my_stack.push(p);
178 178             if(NULL!=p.pBTNode->lchild)
179 179                 my_stack.push(StackNode(p.pBTNode->lchild, true, true));
180 180 
181 181         }
182 182         else
183 183         {
184 184             if(true == p.right)
185 185             {
186 186                 p.right = false;
187 187                 my_stack.pop();
188 188                 my_stack.push(p);
189 189                 if(NULL != p.pBTNode->rchild)
190 190                     my_stack.push(StackNode(p.pBTNode->rchild, true, true));
191 191             }
192 192             else
193 193             {
194 194                 printf("%d ", p.pBTNode->data);
195 195                 my_stack.pop();
196 196             }
197 197         }
198 198     }
199 199 }
200 200 // 根据先序和中序建树
201 201 BTNode* ConsrtcutTree(int pre[], int preL, int preR, int mid[], int midL, int midR)
202 202 {
203 203     BTNode* root = (BTNode*)malloc(sizeof(BTNode));
204 204     root->data = pre[preL];
205 205     root->lchild = root->rchild = NULL;
206 206     if(preL == preR)return root;
207 207     int k = pre[preL];
208 208     int num = 0;
209 209     int pos = midL;
210 210     while(mid[pos]!=k)
211 211     {
212 212         num++;
213 213         pos++;
214 214     }
215 215     if(pos > midL)root->lchild = ConsrtcutTree(pre, preL+1, preL+num, mid, midL, pos - 1);
216 216     if(pos < midR)root->rchild = ConsrtcutTree(pre, preL+num+1, preR, mid, pos+1, midR);
217 217 
218 218     return root;
219 219 
220 220 }
221 221 int main()
222 264 {
223 265     /*数据
224 
225             7
226             7 4 9 5 9 6 8
227             7
228             7 4 5 6 9 9 8
229             4 5 6 7 8 9 9
230 
231  
232 
233 
234        */
235 266     //freopen("data.txt", "r", stdin);
236 267     BTNode* root = NULL;
237 268     int n,a;
238 269     scanf("%d", &n);
239 270     for(int i = 0; i < n;++i)
240 271     {
241 272         scanf("%d", &a);
242 273         InsertBTNode(root, a);
243 274     }
244 275     printf("
先序遍历:
");
245 276     PreOrderTraverse(root);
246 277     printf("
中序遍历:
");
247 278     MidOrderTraverse(root);
248 279     printf("
后序遍历:
");
249 280     LastOrderTraverse(root);
250 281     printf("
非递归先序遍历:
");
251 282     Pre_NoRecurTraverse(root);
252 283 
253 284     printf("
非递归中序遍历:
");
254 285     Mid_NoRecurTraverse(root);
255 286 
256 287     printf("
非递归后序遍历:
");
257 288     Last_NoRecurTraverse(root);
258 289 
259 290 
260 291     printf("根据先序和中序建树:
");
261 292     scanf("%d", &n);
262 293     printf("输入先序:
");
263 294     int pre[maxn];
264 295     int mid[maxn];
265 296     for(int i = 0 ; i < n;++i)
266 297         scanf("%d", &pre[i]);
267 298     printf("输入中序:
");
268 299     for(int i = 0 ; i < n;++i)
269 300         scanf("%d", &mid[i]);
270 301     BTNode* head = NULL;
271 302     head = ConsrtcutTree(pre, 0, n-1, mid, 0, n-1);
272 303 
273 304     printf("
先序遍历:
");
274 305     PreOrderTraverse(head);
275 306 
276 307     printf("
将树序列化树:
");
277 308     char str[maxn];
278 309     num = 0;
279 310     PreLinearTree(root, str);
280 311 
281 312     printf("
将序列化变为树:
");
282 313     BTNode* p = NULL;
283 314     pos = 0;
284 315     p = ReverseLinearTree(str);
285 316     printf("
先序遍历:
");
286 317     PreOrderTraverse(p);
287 318 
288 319 
289 320 
290 321 
291 322 }
View Code

序列化的意思是将内存中的一些特定的结构,变成有格式信息的字符串。如,对于链表而言,我们可以将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

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

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