UVA #10410 树重建

发布于 2024-08-29 11:29:57 字数 1468 浏览 1 评论 0原文

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

梦途 2024-09-05 11:29:57

我想我已经掌握了窍门。但我并不假装它很有效率。

让我们看看 BFS 输出的前 3 位数字:

4 3 5

我们处于以下情况之一:

  4         4
/  \   OR   |
3  5        3
x  x        |
            5
            x

这 2 种情况的 DFS 是多少?

  • 4 3 (3s-children) 5 (5s-children)
  • 4 3 5 (5s-children)

快速说明:如果 3 没有任何子级,那么就不可能区分这两个...

如果我们认为问题是可判定的,那么就需要知道 DFS 表示中 5 是否位于 3 之后。

  • 如果是:它是一个线性组合
  • 如果不是,则进行递归:4 有 2 个子级 35,您可以轻松识别来自 DFS 表示的子树。然后从你拥有的 BFS 中提取(保留顺序)这些子树的 BFS 表示并递归:)

这似乎离最佳状态还很远,但我更担心不确定性。

表达式解析树中是否存在一个约束,即一旦您有一个只有一个子节点的节点,它所代表的子树中的所有节点都不能拥有多个子节点?

I think I have the hang of it. I don't pretend it's efficient though.

Let's look at the first 3 digits of the BFS output:

4 3 5

We are in one of these situations:

  4         4
/  \   OR   |
3  5        3
x  x        |
            5
            x

What is the DFS for those 2 cases ?

  • 4 3 (3s-children) 5 (5s-children)
  • 4 3 5 (5s-children)

Quick note: if 3 does not have any child, then it's impossible to tell the two apart...

If we consider that the problem is decidable, then it's a matter of knowing if 5 follows 3 in the DFS representation.

  • If it does: it's a linear composition
  • If it does not then you go recursive: 4 has 2 children 3 and 5 and you can easily identify the subtree from the DFS representation. Then extract (preserving order) the BFS representation of these subtrees from the BFS you had and recurse :)

It seems fairly far from optimal, but I am a bit more worried about the undecidability.

Is there a constraint in expression-parse trees which states that once you have a node that only has one child none of the nodes in the subtree it represents can have more than one ?

青衫负雪 2024-09-05 11:29:57

“请注意,当父级展开时,子级将在
升序。”

这句话很重要!

#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>

using namespace std;

struct Node
{
    int value;
    Node *child; //left child
    Node *sibling; //right sibling

    Node(int v)
    {
        value = v;
        child = NULL;
        sibling = NULL;
    }
};

void BuildTree(Node *&root,vector<int> bfs,vector<int> dfs)
{
    root = NULL;
    if(bfs.size() == 1)
        root = new Node(bfs[0]);
    if(bfs.size() > 1)
    {
        root = new Node(bfs[0]);

        vector<int> candidate; //store candidate childs
        unsigned i;
        for(i = 1; i < bfs.size(); i++)
        {
            if(bfs[i] >= bfs[1])
                candidate.push_back(bfs[i]);
            else
                break;
        }

        //remove the non-candidate node
        int boundOfChild = candidate.size() - 1;
        for(i = candidate.size() - 1; i >= 1; i--)
        {
            vector<int>::iterator it1;
            vector<int>::iterator it2;
            it1 = find(dfs.begin(),dfs.end(),candidate[i]);
            it2 = find(dfs.begin(),dfs.end(),candidate[i - 1]);
            if(it1 < it2)
                boundOfChild = i;
        }
        if(boundOfChild != candidate.size() - 1)
            candidate.erase(candidate.begin() + boundOfChild,candidate.end());

        //get every child's bfs and dfs
        for(i = candidate.size(); i >= 1; i--)
        {
            vector<int>::iterator it1;
            vector<int>::iterator it2;
            if(i == candidate.size())
            {
                it1 = find(dfs.begin(),dfs.end(),candidate[i - 1]);
                it2 = dfs.end();
            }
            else
            {
                it1 = find(dfs.begin(),dfs.end(),candidate[i - 1]);
                it2 = find(dfs.begin(),dfs.end(),candidate[i]);
            }

            vector<int> tmp_dfs(it1,it2);
            vector<int> tmp_bfs;
            for(vector<int>::iterator it = bfs.begin(); it < bfs.end(); it++)
            {
                if(find(tmp_dfs.begin(),tmp_dfs.end(),*it) != tmp_dfs.end())
                    tmp_bfs.push_back(*it);
            }

            Node *tmp = root->child;
            BuildTree(root->child,tmp_bfs,tmp_dfs);
            root->child->sibling = tmp;
        }
    }
}

void PrintTree(Node *root)
{
    if(root == NULL)
        return;
    queue<Node*> Q;
    Q.push(root);
    while(!Q.empty())
    {
        Node *tmp = Q.front();
        Q.pop();
        cout << tmp->value << ": ";
        tmp = tmp->child;
        while(tmp)
        {
            cout << tmp->value << ",";
            Q.push(tmp);
            tmp = tmp->sibling;
        }
        cout << endl;
    }
}

//just test case
int BFS[] = {7,8,12,4,5,1,6,11,2,3,10,9,13,14};
int DFS[] = {7,8,4,5,2,3,12,1,6,10,14,11,9,13};

int main()
{
    vector<int> vBFS(BFS,BFS + sizeof(BFS) / sizeof(int));
    vector<int> vDFS(DFS,DFS + sizeof(DFS) / sizeof(int));

    Node *root = NULL;
    BuildTree(root,vBFS,vDFS);    
    PrintTree(root);

    return 0;
}

"Note that when a parent was expanded the children were traversed in
ascending order."

This sentence is very important!

#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>

using namespace std;

struct Node
{
    int value;
    Node *child; //left child
    Node *sibling; //right sibling

    Node(int v)
    {
        value = v;
        child = NULL;
        sibling = NULL;
    }
};

void BuildTree(Node *&root,vector<int> bfs,vector<int> dfs)
{
    root = NULL;
    if(bfs.size() == 1)
        root = new Node(bfs[0]);
    if(bfs.size() > 1)
    {
        root = new Node(bfs[0]);

        vector<int> candidate; //store candidate childs
        unsigned i;
        for(i = 1; i < bfs.size(); i++)
        {
            if(bfs[i] >= bfs[1])
                candidate.push_back(bfs[i]);
            else
                break;
        }

        //remove the non-candidate node
        int boundOfChild = candidate.size() - 1;
        for(i = candidate.size() - 1; i >= 1; i--)
        {
            vector<int>::iterator it1;
            vector<int>::iterator it2;
            it1 = find(dfs.begin(),dfs.end(),candidate[i]);
            it2 = find(dfs.begin(),dfs.end(),candidate[i - 1]);
            if(it1 < it2)
                boundOfChild = i;
        }
        if(boundOfChild != candidate.size() - 1)
            candidate.erase(candidate.begin() + boundOfChild,candidate.end());

        //get every child's bfs and dfs
        for(i = candidate.size(); i >= 1; i--)
        {
            vector<int>::iterator it1;
            vector<int>::iterator it2;
            if(i == candidate.size())
            {
                it1 = find(dfs.begin(),dfs.end(),candidate[i - 1]);
                it2 = dfs.end();
            }
            else
            {
                it1 = find(dfs.begin(),dfs.end(),candidate[i - 1]);
                it2 = find(dfs.begin(),dfs.end(),candidate[i]);
            }

            vector<int> tmp_dfs(it1,it2);
            vector<int> tmp_bfs;
            for(vector<int>::iterator it = bfs.begin(); it < bfs.end(); it++)
            {
                if(find(tmp_dfs.begin(),tmp_dfs.end(),*it) != tmp_dfs.end())
                    tmp_bfs.push_back(*it);
            }

            Node *tmp = root->child;
            BuildTree(root->child,tmp_bfs,tmp_dfs);
            root->child->sibling = tmp;
        }
    }
}

void PrintTree(Node *root)
{
    if(root == NULL)
        return;
    queue<Node*> Q;
    Q.push(root);
    while(!Q.empty())
    {
        Node *tmp = Q.front();
        Q.pop();
        cout << tmp->value << ": ";
        tmp = tmp->child;
        while(tmp)
        {
            cout << tmp->value << ",";
            Q.push(tmp);
            tmp = tmp->sibling;
        }
        cout << endl;
    }
}

//just test case
int BFS[] = {7,8,12,4,5,1,6,11,2,3,10,9,13,14};
int DFS[] = {7,8,4,5,2,3,12,1,6,10,14,11,9,13};

int main()
{
    vector<int> vBFS(BFS,BFS + sizeof(BFS) / sizeof(int));
    vector<int> vDFS(DFS,DFS + sizeof(DFS) / sizeof(int));

    Node *root = NULL;
    BuildTree(root,vBFS,vDFS);    
    PrintTree(root);

    return 0;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文