题解 UVA122 【树的层次遍历 Trees on the level】

By《算法竞赛入门经典》

前几天终于自学到树了,这道题作为例题自然是比较需要重点掌握了。

感觉这道题我在怎么讲解肯定也没有lrj讲得好,所以我这篇题解主要是lrj的思想。

最重要的是树的存储

可以用两种方法

  1. 结构体+指针

    struct Node{
     bool have_value;//是否被赋值过,这个是针对本题要求设定的
     int v;//结点的值
     Node* left, *right;
     Node():have_value(false),left(NULL),right(NULL){}//构造函数(大概就是初始化的意思吧)
    }*root;//二叉树的根结点

    由于二叉树是递归定义的,其左右子结点类型都是“指向结点类型的指针”。换句话说, 如果结点的类型为Node,则左右子结点的类型都是Node *。

    每次需要一个新的Node时,都要用new运算符申请内存,并执行构造函数。下面把申请 新结点的操作封装到newnode函数中:

    Node* newnode() { return new Node(); }

    还有这里lrj还提到了一个问题,当每次执行root=newnode()之后,之后这些内存就变成无法访问的内存垃圾了,因此最好写一个递归函数专门来清理这些内存。

    下面是释清理内存的代码,请在“root = newnode()”之前加一 行“remove_tree(root)”:

    void remove_tree(Node* u) {  
       if(u == NULL) return;//提前判断比较稳妥  
       remove_tree(u->left);//递归释放左子树的空间
       remove_tree(u->right);//递归释放右子树的空间 
       delete u;//调用u的析构函数并释放u结点本身的内存 
    }
  2. 数组+下标

    首先还是给每个结点编号, 但不是按照从上到下从左到右的顺序,而是按照结点的生成顺序。用计数器cnt表示已存在的 结点编号的最大值,因此newnode函数需要改成这样:

    const int root = 1;    
    void newtree() { 
       left[root] = right[root] = 0; 
       have_value[root] = false; 
       cnt = root;
    }    
    int newnode() { 
       int u = ++cnt; 
       left[u] = right[u] = 0; 
       have_value[root] = false; 
       return u; 
    }

    上面的newtree()是用来代替前面的“remove_tree(root)”和“root = newnode()”两条语句的: 由于没有了动态内存的申请和释放,只需要重置结点计数器和根结点的左右子树了。 接下来,把所有的Node类型改成int类型,然后把结点结构中的成员变量改成全局数组 (例如,u->left和u->right分别改成left[u]和right[u]),除了char外,整个程序就没有任何指 针了。

存储完树之后,这道题就没什么难点了,直接BFS就可以了。

$my-code$

#include <cstdio>
#include <vector>
#include <queue>
#include <cstring>
#define maxn 1001000

using namespace std;

struct Node {
    bool have_value;
    int v;
    Node *left,*right;
    Node():have_value(false),left(NULL),right(NULL){}
};

int v;
bool failed;
char s[maxn];

Node* root;
Node* newnode(){return new Node();}

inline void remove_tree(Node *p) {
    if(p == NULL) {
        return ;
    }
    remove_tree(p->left);
    remove_tree(p->right);
    delete p;
}

inline bool BFS(vector<int> &ans) {
    ans.clear();
    queue<Node* > Q;
    Q.push(root);
    while(!Q.empty()) {
        Node* u=Q.front();Q.pop();
        if(!u->have_value) {
            return false;
        }
        ans.push_back(u->v);
        if(u->left != NULL) {
            Q.push(u->left);
        }
        if(u->right != NULL) {
            Q.push(u->right);
        }
    }
    return true;
}
inline void add_Node(int v,char *s) {
    int n=strlen(s);
    Node *u=root;
    for(int i=0; i<n; i++) {
        if(s[i] == 'L') {
            if(u->left == NULL) {
                u->left=newnode();
            }
            u=u->left;
        }
        if(s[i] == 'R') {
            if(u->right == NULL) {
                u->right=newnode();
            }
            u=u->right;
        }
    }
    if(u->have_value) {
        failed=true;
    }
    u->v=v;
    u->have_value=true;
}

inline bool read_input() {
    failed=false;
    remove_tree(root);
    root=newnode();
    for( ;; ) {
        if(scanf("%s", s) != 1) {
            return false;
        }
        if(strcmp(s,"()") == 0) {
            break;
        }
        sscanf(&s[1],"%d",&v);
        add_Node(v,strchr(s,',')+1);
    }
    return true;
}

int main()
{
    vector<int> ans;
    while(read_input()) {
        if(failed || !BFS(ans)) {
            printf("not complete");
        }else {
            for(vector<int>::iterator t=ans.begin(); t!=ans.end(); t++) {
                if(t != ans.end()-1) {
                    printf("%d ",*t);
                }else {
                    printf("%d",*t);
                }
            }
        }
        printf("\n");
    }
    return 0;
}
posted @ 2018-12-24 22:16  加固文明幻景  阅读(8)  评论(0编辑  收藏  举报  来源