简体   繁体   English

使用 C++ 智能指针构建带有父指针的树

[英]Building tree with a parent pointer using C++ smart pointers

I'm trying to build a binary tree with smart pointers, where nodes also include a parent pointer.我正在尝试使用智能指针构建二叉树,其中节点还包括父指针。 To do that, I defined the children pointers as shared_ptr and the parent pointers as weak_ptr .为此,我将子指针定义为shared_ptr ,将父指针定义为weak_ptr

The best I could come up with is the following:我能想到的最好的方法如下:

#include <iostream>
#include <memory>

using namespace std;

struct Node;

struct NodeBase {
    int val;

    NodeBase(int v) : val(v) {}

    virtual void add_node_left(shared_ptr<Node> &ptr, int v) = 0;
    virtual void add_node_right(shared_ptr<Node> &ptr, int v) = 0;

    virtual ~NodeBase() {};
};

struct NodePtr {
    shared_ptr<NodeBase> ptr;

    template<typename... Args>
    NodePtr(Args&&... args) : ptr(std::forward<Args>(args)...) {}

    void add_left(int v) {
        shared_ptr<Node> node_ptr = std::static_pointer_cast<Node>(ptr);
        ptr->add_node_left(node_ptr, v);
    }

    void add_right(int v) {
        shared_ptr<Node> node_ptr = std::static_pointer_cast<Node>(ptr);
        ptr->add_node_right(node_ptr, v);
    }
};

struct Node : public NodeBase {
    NodePtr left, right;
    weak_ptr<Node> parent;

    Node(int v) : NodeBase(v), left(nullptr), right(nullptr), parent() {}

    shared_ptr<Node> make_child(shared_ptr<Node> &selfptr, int v) {
        auto child = make_shared<Node>(v);
        child->parent = selfptr;
        return child;
    }

    void virtual add_node_left(shared_ptr<Node> &selfptr, int v) {
        left = make_child(selfptr, v);
    }

    void virtual add_node_right(shared_ptr<Node> &selfptr, int v) {
        right = make_child(selfptr, v);
    }


    virtual ~Node() {};
};

struct Tree {
    NodePtr root;

    Tree() : root(nullptr) {};
    Tree(int val) {
        add_root(val);
    }

    void add_root(int val) {
        root = make_shared<Node>(val);
    }
};

int main() {
    Tree tree;
    tree.add_root(10);
    tree.root.add_left(5);
    tree.root.add_right(12);
}

First of all, is this correct?首先,这是正确的吗?

Second, I'm not very fond of having to define the NodeBase base class.其次,我不太喜欢定义NodeBase基础 class。 The reason for it is so I can pass the shared_ptr to add_node_left and add_node_right , needed to create the parent weak_ptr .这样做的原因是我可以将shared_ptr传递给add_node_leftadd_node_right ,这是创建父weak_ptr所需的。 Is there a way to do this that avoids NodeBase but maintains the same (or similar) interface?有没有办法避免NodeBase但保持相同(或相似)的接口?

You don't need NodeBase nor NodePtr .您不需要NodeBase也不需要NodePtr

struct Node : std::enable_shared_from_this {
    int val;
    std::shared_ptr<Node> left, right;
    std::weak_ptr<Node> parent;

    Node(int v, std::weak_ptr<Node> p) : val(v), left(), right(), parent(p) {}

    void add_node_left(int v) {
        left = std::make_shared<Node>(v, weak_from_this()); // shared_from_this() pre C++17
    }

    void add_node_right(int v) {
        right = std::make_shared<Node>(v, weak_from_this()); // shared_from_this() pre C++17
    }
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM