树结构中的C++指针

C++ pointers in tree structure

本文关键字:C++ 指针 结构      更新时间:2023-10-16

我正在尝试为海上导航算法实现一些基本的树结构。我有这样的东西:

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 个级别的递归树,但只创建一个级别的树。我认为这是父指针的问题,但我无法意识到到底发生了什么。

您的代码存在几个问题

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);
        }
}

您还可以跟踪树深度作为每个节点的数据成员。不幸的是,由于您未能提供最小完整且可验证的示例,因此我无法在此处进行测试。

另请注意,您的代码没有用于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);
        }
    }
}