UVa 122 (二叉树的层次遍历) Trees on the level
题意:
输入一颗二叉树,按照(左右左右, 节点的值)的格式。然后从上到下从左到右依次输出各个节点的值,如果一个节点没有赋值或者多次赋值,则输出“not complete”
一、指针方式实现二叉树
首先定义一个结构体,然后定义一个结构体指针root,作为整棵树的根节点。如果需要用到左右节点则申请一个空间,也就是用不到的就不申请,以节省空间。
遍历方式是广度优先遍历(BFS),从根节点依次拓展子节点,如果有子节点就入队,然后根节点出队。继续拓展,直到队列为空,即遍历完整棵树。
因为指针丢失以后会造成内存泄露,所以在每次读取二叉树之前都要释放掉上一棵树申请的内存,二叉树的删除也是递归删除的。
1 #define LOCAL 2 #include <iostream> 3 #include <cstdio> 4 #include <cstring> 5 #include <vector> 6 #include <queue> 7 8 const int maxn = 300; 9 char s[maxn]; 10 bool failed; 11 std::vector<int> ans; 12 13 struct Node 14 { 15 bool have_value; //是否赋值过 16 int v; 17 Node *left, *right; 18 Node():have_value(false), left(NULL), right(NULL) {} //构造函数 19 }; 20 Node* root; 21 22 Node* newnode() { return new Node(); } //调用构造函数 23 24 void addnode(int v, char* s) 25 { 26 int n = strlen(s); 27 Node* u = root; 28 for(int i = 0; i < n; ++i) 29 { 30 if(s[i] == 'L') 31 { 32 if(u->left == NULL) u->left = newnode(); 33 u = u->left; 34 } 35 else if(s[i] == 'R') 36 { 37 if(u->right == NULL) u->right = newnode(); 38 u = u->right; 39 } 40 } 41 if(u->have_value) failed = true; //如果一个节点有多次赋值,做标记 42 u->v = v; 43 u->have_value = true; 44 } 45 46 void remove_tree(Node* u) 47 { 48 if(u == NULL) return; 49 remove_tree(u->left); 50 remove_tree(u->right); 51 delete u; 52 } 53 54 bool read_input(void) 55 { 56 failed = false; 57 remove_tree(root); 58 root = newnode(); 59 60 for(;;) 61 { 62 if(scanf("%s", s) != 1) return false; 63 if(!strcmp(s, "()")) break; 64 int v; 65 sscanf(&s[1], "%d", &v); 66 addnode(v, strchr(s, ',') + 1); 67 } 68 return true; 69 } 70 71 bool BFS(std::vector<int>& ans) 72 { 73 std::queue<Node*> q; 74 ans.clear(); 75 q.push(root); 76 while(!q.empty()) 77 { 78 Node* u = q.front(); 79 q.pop(); 80 if(!u->have_value) return false; //该节点没有赋值过 81 ans.push_back(u->v); 82 if(u->left != NULL) q.push(u->left); 83 if(u->right != NULL) q.push(u->right); 84 } 85 return true; 86 } 87 88 int main(void) 89 { 90 #ifdef LOCAL 91 freopen("122in.txt", "r", stdin); 92 #endif 93 94 while(read_input()) 95 { 96 if(failed || !BFS(ans)) printf("not complete\n"); 97 else 98 { 99 printf("%d", ans[0]); 100 for(int i = 1; i < ans.size(); ++i) 101 printf(" %d", ans[i]); 102 puts(""); 103 } 104 } 105 106 return 0; 107 }
二、数组方式实现
每新建一个节点计数器cnt就自增1,而不是像完全二叉树那样,左右子节点是父节点的二倍和二倍加1.
1 //#define LOCAL 2 #include <iostream> 3 #include <cstdio> 4 #include <cstring> 5 #include <queue> 6 #include <vector> 7 8 const int maxn = 300; 9 const int root = 1; 10 char s[maxn]; 11 bool have_value[maxn], failed; 12 int left[maxn], right[maxn], val[maxn], cnt; 13 std::vector<int> ans; 14 15 void newtree(void) 16 { 17 left[root] = right[root] = 0; 18 have_value[root] = false; 19 cnt = root; 20 } 21 22 int newnode(void) 23 { 24 int u = ++cnt; 25 left[u] = right[u] = 0; 26 have_value[u] = false; 27 return u; 28 } 29 30 void addnode(int v, char* s) 31 { 32 int n = strlen(s); 33 int u = root; 34 for(int i = 0; i < n; ++i) 35 { 36 if(s[i] == 'L') 37 { 38 if(left[u] == 0) left[u] = newnode(); 39 u = left[u]; 40 } 41 else if(s[i] == 'R') 42 { 43 if(right[u] == 0) right[u] = newnode(); 44 u = right[u]; 45 } 46 } 47 if(have_value[u]) failed = true; //如果一个节点有多次赋值,做标记 48 val[u] = v; 49 have_value[u] = true; 50 } 51 52 bool read_input(void) 53 { 54 failed = false; 55 newtree(); 56 57 for(;;) 58 { 59 if(scanf("%s", s) != 1) return false; 60 if(!strcmp(s, "()")) break; 61 int v; 62 sscanf(&s[1], "%d", &v); 63 addnode(v, strchr(s, ',') + 1); 64 } 65 return true; 66 } 67 68 bool BFS(std::vector<int>& ans) 69 { 70 std::queue<int> q; 71 ans.clear(); 72 q.push(root); 73 while(!q.empty()) 74 { 75 int u = q.front(); 76 q.pop(); 77 if(!have_value[u]) return false; 78 ans.push_back(val[u]); 79 if(left[u] != 0) q.push(left[u]); 80 if(right[u] != 0) q.push(right[u]); 81 } 82 return true; 83 } 84 85 int main(void) 86 { 87 #ifdef LOCAL 88 freopen("122in.txt", "r", stdin); 89 #endif 90 91 while(read_input()) 92 { 93 if(failed || !BFS(ans)) puts("not complete"); 94 else 95 { 96 printf("%d", ans[0]); 97 for(int i = 1; i < ans.size(); ++i) 98 printf(" %d", ans[i]); 99 puts(""); 100 } 101 } 102 103 return 0; 104 }
三、内存池的方法
静态申请一个Node数组配合一个空闲列表实现一个简单的内存池。
1 //#define LOCAL 2 #include <iostream> 3 #include <cstdio> 4 #include <cstring> 5 #include <vector> 6 #include <queue> 7 8 const int maxn = 300; 9 char s[maxn]; 10 bool failed; 11 std::vector<int> ans; 12 13 struct Node 14 { 15 bool have_value; //是否赋值过 16 int v; 17 Node *left, *right; 18 Node():have_value(false), left(NULL), right(NULL) {} //构造函数 19 }node[maxn]; 20 Node* root; 21 std::queue<Node*> freenodes; 22 23 void Init() 24 { 25 for(int i = 0; i < maxn; ++i) 26 freenodes.push(&node[i]); //初始化内存池 27 } 28 29 Node* newnode() 30 { 31 Node* u = freenodes.front(); 32 u->left = u->right = NULL; 33 u->have_value = false; 34 freenodes.pop(); 35 return u; 36 } 37 38 void deletenode(Node* u) { freenodes.push(u); } 39 40 void addnode(int v, char* s) 41 { 42 int n = strlen(s); 43 Node* u = root; 44 for(int i = 0; i < n; ++i) 45 { 46 if(s[i] == 'L') 47 { 48 if(u->left == NULL) u->left = newnode(); 49 u = u->left; 50 } 51 else if(s[i] == 'R') 52 { 53 if(u->right == NULL) u->right = newnode(); 54 u = u->right; 55 } 56 } 57 if(u->have_value) failed = true; //如果一个节点有多次赋值,做标记 58 u->v = v; 59 u->have_value = true; 60 } 61 62 void remove_tree(Node* u) 63 { 64 if(u == NULL) return; 65 remove_tree(u->left); 66 remove_tree(u->right); 67 deletenode(u); 68 } 69 70 bool read_input(void) 71 { 72 failed = false; 73 remove_tree(root); 74 Init(); 75 root = newnode(); 76 for(;;) 77 { 78 if(scanf("%s", s) != 1) return false; 79 if(!strcmp(s, "()")) break; 80 int v; 81 sscanf(&s[1], "%d", &v); 82 addnode(v, strchr(s, ',') + 1); 83 } 84 return true; 85 } 86 87 bool BFS(std::vector<int>& ans) 88 { 89 std::queue<Node*> q; 90 ans.clear(); 91 q.push(root); 92 while(!q.empty()) 93 { 94 Node* u = q.front(); 95 q.pop(); 96 if(!u->have_value) return false; //该节点没有赋值过 97 ans.push_back(u->v); 98 if(u->left != NULL) q.push(u->left); 99 if(u->right != NULL) q.push(u->right); 100 } 101 return true; 102 } 103 104 int main(void) 105 { 106 #ifdef LOCAL 107 freopen("122in.txt", "r", stdin); 108 #endif 109 110 while(read_input()) 111 { 112 if(failed || !BFS(ans)) printf("not complete\n"); 113 else 114 { 115 printf("%d", ans[0]); 116 for(int i = 1; i < ans.size(); ++i) 117 printf(" %d", ans[i]); 118 puts(""); 119 } 120 } 121 122 return 0; 123 }