标签:
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 }
反序列化:
用先序遍历的思想每次读取一个结点,如果读取到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 }
当然也可以采用层次遍历的方法来实现序列化,原理是和上面一样的
标签:
原文地址:http://www.cnblogs.com/acSzz/p/5421386.html