【问题标题】:Building tree with a parent pointer using C++ smart pointers使用 C++ 智能指针构建带有父指针的树
【发布时间】:2020-03-01 17:42:57
【问题描述】:

我正在尝试使用智能指针构建二叉树,其中节点还包括父指针。为此,我将子指针定义为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 基类。这样做的原因是我可以将shared_ptr 传递给add_node_left 和add_node_right,这是创建父weak_ptr 所需的。有没有办法避免NodeBase 但保持相同(或相似)的界面?

【问题讨论】:

  • root 应该是unique_ptr,每个节点的子节点也应该是。其他一切都应该是一个普通的指针。这样做的好处是,一旦你修剪了一个孩子,以该孩子为根的子树将自动释放,尽管有一个警告。查看this 链接了解更多信息。

标签: c++ smart-pointers


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-24
    • 1970-01-01
    • 1970-01-01
    • 2014-03-23
    • 1970-01-01
    • 1970-01-01
    • 2011-03-23
    • 1970-01-01
    相关资源
    最近更新 更多