树结构中的C ++指针

时间:2017-03-23 12:40:28

标签: c++ recursion constructor tree this

我试图为海上导航算法实现一些基本的树结构。 我有这样的事情:

class Point {
    float lng;
    float lat;
};

class Node {
public:
    Node *parent;
    std::list<Node> *childern;
    Point *point;
    Node::Node(Node *prnt, Point *point);
    void Node::calcChildrens();
};
Node::Node(Node *prnt, Point *point)  {
    this->parent = prnt;
    this->point = point;
    this->childern = nullptr;
}
int counter = 0;
void Node::calcChildrens() {

    for (int i = 0; i < 5; i++) {

        Point *p = new Point(someValX, someValY);
        Node n = Node(this, p);

        if (this->childern == NULL) this->childern = new list<Node>;
        this->childern->push_back(n);
        if (counter < 4) {
            counter++;
            n.calcChildrens();
        }
}

这应该创建4级递归树,但只创建一个级别的树。 我认为这是父指针的问题,但我无法意识到真正发生的事情。

1 个答案:

答案 0 :(得分:1)

您的代码有几个问题

struct Point {   // we want public access, hence struct not class
    float lng;
    float lat;
};

struct Node {    // if all members a public, use struct
    Node*parent = nullptr;             // provide default argument
    std::list<Node> children;          // hold a list, not a pointer to one
    Point point;                       // hold a Point, not a pointer to one
    Node(Node*p, const Point&x)
    : parent(p), point(x) {}           // use initialization list
    void calcChildren(size_t levels);  // avoid global variable counter; use correct English
};

void Node::calcChildren(size_t levels)
{
    if(levels--)
        for(int i = 0; i < 5; i++) {   // really 5? 4 children seems more logical
            // construct child in place, avoid copying a Node    
            children.emplace_back(this, Point{someValX, someValY});
            children.back().calcChildren(levels);
        }
}

您还可以将树深度跟踪为每个节点的数据成员。不幸的是,由于您未能提供Minimal Complete and Verifiable Example,我无法在此进行测试。

另请注意,您的代码没有Node的析构函数,泄漏了分配给节点的所有内存。当避免那些指针有利于对象时,这个问题就消失了。无论如何,在堆上分配Node,这是用C ++做事的逻辑和正确方法。

进一步注意,您可能希望避免将子项保留在链接列表中(如果效率很重要,则应避免链接列表)。您可以改为使用数组或vector。在这种情况下

struct Node {    // if all members a public, use struct
    Node*parent = nullptr;             // provide default argument
    std::vector<Node> children;        // hold a vector, not a pointer to one
    Point point;                       // hold a Point, not a pointer to one
    Node(Node*p, const Point&x)
    : parent(p), point(x) {}           // use initialization list
    void calcChildren(size_t levels);  // avoid global variable counter; use correct English
};

void Node::calcChildren(size_t levels)
{
    if(levels--) {
        children.reserve(5);
        for(int i = 0; i < 5; i++) {
            // construct child in place, avoid copying a Node    
            children.emplace_back(this, Point{someValX, someValY});
            children.back().calcChildren(levels);
        }
    }
}