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
");
 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
");
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 }
代码君三

相关推荐