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

Building tree with a parent pointer using C++ smart pointers

我正在尝试构建一个带有智能指针的二叉树,其中节点还包含一个父指针。为此,我将子指针定义为 shared_ptr,将父指针定义为 weak_ptr

我能想到的最好的是:

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

首先,这是正确的吗?

其次,我不太喜欢定义 NodeBase 基础 class。这样做的原因是我可以将 shared_ptr 传递给 add_node_leftadd_node_right,需要创建父 weak_ptr。有没有一种方法可以避免 NodeBase 但保持相同(或相似)的界面?

您不需要 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
    }
};