与多个孩子的树使用传染媒介

时间:2014-11-18 20:01:34

标签: c++ vector tree

我试图制作一个有多个孩子的树,这棵树应该看起来如下:

      n 
/     |     \
n2    n3     n4
|
n5  

每个节点都有自己的因素,我的任务是计算所有节点的数量,例如n5的数量是n.factor * n2.factor * n5.factor。

我认为问题在于指针,但我不知道如何处理它。

关于可能出错的一些想法在下面的代码中。

Obiekt.h

#include <string>
using namespace std;
class Obiekt
{
private:
string name;


public:
    Obiekt();
    Obiekt(string name);

    void wyswietlObiekt();
    string getName();

    ~Obiekt();
};

Node.h:

#include "Obiekt.h"
#include <vector>
#include <string>


using namespace std;

class Node {

public:

    Node();
    Node(Obiekt ob, double factor);

    void add(Node node);
    void show();
    vector<Node> getChildrenList();
    double getFactor();
    Obiekt getObiekt();


private:
    vector<Node> children;
    double factor;
    Obiekt obiekt;

};

Node.cpp:

#include "Node.h"
#include <string>
#include <vector>
#include <iostream>
#include <sstream>
#include <cstdlib>

using namespace std;


Node::Node()
{
    obiekt = Obiekt();
    factor = 0.0;
}

Node::Node(Obiekt ob, double mn)
{
    obiekt = ob;
    factor = mn;
}

void Node::show()
{
    for (int i = 0; i < children.size(); i++) {

        cout << children[i].getFactor() << endl;
    }
}


void Node::add(Node node)
{
    children.push_back(node);
}



vector<Node> Node::getChildrenList()
{
    return children;
}

double Node::getFactor()
{
    return factor;
}

Obiekt Node::getObiekt()
{
    return obiekt;
}

tree.h中:

#include <string>
#include <vector>
#include "Node.h"

using namespace std;


class Tree
{

public:
    Tree();

    void addNode(Node *parent, Obiekt o, double mnoznik);
    void addNode(Node *parent, Node wezel);
    void deleteTree();
    double countNodes(Node node, string key);
    vector<Node*> getList();
    double search(string key);

private:
    vector<Node*> nodeTree;
    Node root;
};

和Tree.cpp:

#include "Tree.h"
#include <string>
#include <vector>
#include <iostream>
#include <sstream>
#include <cstdlib>

using namespace std;

Tree::Tree()
{
    root = Node();
}

void Tree::addNode(Node *parent, Obiekt o, double mnoznik)
{
    Node n(o, mnoznik);

    nodeTree.push_back(&n);

    if (parent == NULL)
    {
        root = Node(o, mnoznik);
        cout << "mnoznik korzenia: " << root.getFactor() << endl;
    }
    else
    {
        parent->add(n);
    }
}

void Tree::addNode(Node *parent, Node wezel)
{
    nodeTree.push_back(&wezel);

    if (parent == NULL)
    {
        root = wezel;
        cout << "mnoznik korzenia: " << root.getFactor() << endl;
    }
    else
    {
        parent->add(wezel);
        cout << "added: " << wezel.getFactor() << endl;
    }
}

double Tree::countNodes(Node node, string key)
{
    int rozmiar = nodeTree.size();

    double factor = node.getFactor();
    double iloczynTemp = 1.0;
    double quantity = 0.0;

    for (Node node : node.getChildrenList())
    {
        iloczynTemp = factor * node.getFactor();

        if (node.getObiekt().getNazwa() == key)
        {
            quantity = quantity + iloczynTemp;
        }

        quantity = quantity + countNodes(node, key);
    }

    return quantity;
}

double Tree::search(string key)
{
    double wynik = 0.0;
    for (Node *n : nodeTree)
    {
        if (n->getObiekt().getNazwa() == key)
        {
            wynik = wynik + n->getFactor();
        }
    }
    return wynik;
}


void Tree::deleteTree()
{
    nodeTree.clear();
}


vector<Node*> Tree::getList()
{
    return nodeTree;
}

int main()
{

    Tree tree;

    Node n(Obiekt("n"), 1.0);

    tree.addNode(NULL, n);

    Node n2(Obiekt("n2"), 2.0);
    tree.addNode(&n, n2);
    Node n3(Obiekt("n3"), 3.0);
    tree.addNode(&n, n3);
    Node n4(Obiekt("n4"), 4.0);
    tree.addNode(&n, n4);

    Node n5(Obiekt("n5"), 5.0);
    tree.addNode(&n2, n5);

    n.show();

    cout << n.getChildrenList().size() << endl;
    cout << n2.getChildrenList().size() << endl;
    cout << n.getChildrenList()[0].getChildrenList().size() << endl;


    system("pause");
    return 0;
}

问题出现在main()

cout << n.getChildrenList().size() << endl;      // right result = 3
cout << n2.getChildrenList().size() << endl;     // right result = 1
cout << n.getChildrenList()[0].getChildrenList().size() << endl;  // wrong result, should be 1 like above, but it is 0, why?

另一个问题是Tree.cpp中的countNodes方法:

    quantity = quantity + countNodes(node, key); // why countNodes(node, key) is 0, it should be 0 when node don't have children, but some of them has.

提前谢谢你,bakii!

1 个答案:

答案 0 :(得分:2)

我在此代码中看到的最大问题是您正在混合指针和按值传递的项目。一个不好的例子:

void Tree::addNode(Node *parent, Obiekt o, double mnoznik)
{
    Node n(o, mnoznik);

    nodeTree.push_back(&n);
    ...

在此行中,您将在addNode()函数的上下文中在堆栈上创建一个本地对象,然后将其地址推送到向量中。在此功能结束时, n 将超出范围,地址将不再有效。很可能在随后的调用中,地址将被重用,但是您在未定义的行为中退出,并且Nothing Good可以来自它。

对于这种结构,您可能希望一直使用指针。不要像这样在堆栈上分配节点,而是需要类似的东西:

Node* n = new Node(o, mnoznik);
nodeTree.push_back(&n);

在析构函数中,您需要删除向量中的所有节点。

通过更多的工作,你可以提出一个基于全值的树,或者能够使用智能指针来处理你的内存管理,但我称之为超出这个问题的范围。