从文件重建二叉树

时间:2010-09-07 08:52:15

标签: c++

下面的信息在文件中给出,您必须创建一个函数来重建C ++中的二叉树。

node   leftchild  rtchild

1       2   4
2       $   5
5       6   7
6       $   $
7       $   $
4       $     8
8       $   $

$ - 清空

任何人都可以建议重建二叉树...... ???

我做过: -

void rebuild_btree(node *tree) 
{
    ifstream fin("data.txt");
    string a;

    if (!fin)
        cout << "\nError in opening file.." << endl;
    else
        cout << "\nFile is successfully opened.." << endl;

    while (!fin.eof()) 
    {
        fin >> a;
        tree = insert(tree, a);
    }
    fin.close();
}

node* insert(node *root, string &dat)
{
    if(dat != "$")
    { 
       if(root == NULL)
       {
          root = new node;
          strcpy(root->data, dat);
          root->left = root->right = NULL;
       }
       else if (root->left == NULL)
            root->left = insert(root->left, dat);
       else
            root->right = insert(root->right, dat);
       return root;
    }
    return root;
}

这不起作用..我认为有一些错误,我没有得到......如果你能抓住那么建议我....

2 个答案:

答案 0 :(得分:1)

问题1:

不要这样做:(这是错的)。在您尝试读取EOF之前,EOF标志不会设置,而最后一次成功读取会读取(但不会超过)EOF。所以你再次进入循环所需的时间。

while (!fin.eof()) 
{
    fin >> a;
    tree = insert(tree, a);
}

它应该这样写:这是有效的,因为运算符&gt;&gt;返回对流的引用。当一个流在布尔上下文中使用时(比如一段时间的条件),它被转换为一个可转换为bool的对象,如果没有设置错误标志,则该值为true。因此,如果读取成功,则输入循环,否则不是。

while (fin >> a) 
{
    tree = insert(tree, a);
}

问题2:

这显然不能编译,因为String不是标准类型 类型是字符串(小写s),它位于std :: namespace中。所以请使用std :: string。

如果这是您定义的类型,那么我们需要知道了解这条线是如何工作的:

fin >> a;

问题3:

如果传递的String为“$”,则函数insert()不返回值。 C ++函数必须始终返回一个值(除非返回类型为void)。否则它是'未定义的行为'。

问题4:

Insert()显然无法正常工作。

  • 您不要尝试区分三种不同的输入类型:
    可以是'整数索引''$'或'','。
  • 您不会将输入位置腐蚀为树的结构。

问题5:

您应该考虑二叉树的不同输入格式。由于需要两次通过,因此特别难以解析和重新构建。您需要第一遍才能读取所有节点。然后你需要第二遍来重建树结构。

这显然是功课!

提示:

一次读取一行并正确解析该行:

std::string  line;
std::getline(fin, line);

一次解析整行,并构建一个对象来表示节点。不幸的是,您可以构建真实节点,因为此输入格式需要两次传递。

struct TmpNode { int value; std::string left; std::string right; }  tmp;
std::istringstream data(line);

data >> tmp.value >> tmp.left >> tmp.right;

因为你需要一个两阶段构建1)阅读2)构建树。您需要存储TmpNode个对象,直到您拥有它们并构建树。

std::map<int,TmpNode>  nodes;
nodes[boost::lexical_cast<int>(tmp.value)] = tmp;

将所有TmpNode存储在地图中后。您现在可以轻松地遍历地图并构建树。

node* buildTree(std::string const& nodeID)
{
    if (nodeID == "$") { return NULL;}

    TmpNode& n = nodes[boost::lexical_cast<int>(nodeID)];
    return new node(nodeID, buildTree(n.left), buildTree(n.right));
}

答案 1 :(得分:0)

第一印象:您正在混合使用C和C ++习语:您声明char a[20],将其作为insert()传递给string(使用隐式转换),然后使用{进行比较{1}}(它甚至不应该工作,因为它需要strcmp(),而不是const char*。相反,您应该从一开始就将其声明为string,将其作为string传递以避免不必要的复制,并使用const string&进行比较。

通过递归调用==,您似乎也一遍又一遍地向树中插入相同的值。您应该一次从文件中读取3个值的元组,然后在正确的位置将其作为子树插入一次。

顺便说一句“不工作”是一个非常模糊的描述 - 请详细说明执行时会发生什么。你得到错误的结果,崩溃,无限循环,......?