使用唯一指针将节点添加到树
Posted
技术标签:
【中文标题】使用唯一指针将节点添加到树【英文标题】:adding nodes to tree with unique pointer 【发布时间】:2018-02-16 15:47:07 【问题描述】:我对智能指针非常陌生,我正在尝试创建一个双重树,其中子节点通过唯一指针从父节点指向,子节点通过原始指针指向父节点。所以当一个父节点被销毁时,整个子树都会在这个过程中被销毁。
class Node
private:
Node *parent;
std::unique_ptr<Node> left;
std::unique_ptr<Node> right;
public:
Node(Node* _left, Node* _right, Node* _parent);
;
Node::Node(Node* _left, Node* _right, Node* _parent)
parent = &_parent;
//this is where the problem starts
我不明白如何指向一个可能有我想要连接的树的新节点。如果我使用 make_unique 我相信这将创建一个新节点而不是保留树。
我可能完全错了,因为我大约 4 天前刚刚学习了智能指针(实际上有足够的时间来学习一些东西)。
【问题讨论】:
你传递给构造函数的东西是节点的副本,这不太可能是你想要的。 值传递的参数与其他局部变量没有区别,一旦函数返回就会超出范围。 构造函数中怎么能左右呢?您正在创建一个节点,同时已经知道父节点和子节点? 好吧,正如我在解释中所说,我想要唯一指针类的唯一属性(如果它超出范围,它将被删除),但同时想要访问其父类。 【参考方案1】:首先,一棵空树是可能的,并且默认构造的节点很适合。 父节点在附加节点时就知道了,因此,一旦节点被设置为当前树的左子节点或右子节点,子节点的父节点将被更新。
接收 unique_ptr 可能是一个好主意,因为您拥有所接收指针的所有权。这是一个示例实现:
class Node
private:
Node *parent = nullptr;
std::unique_ptr<Node> m_left;
std::unique_ptr<Node> m_right;
public:
void left(std::unique_ptr<Node> child)
m_left = std::move(child);
m_left->parent = this;
void right(std::unique_ptr<Node> child)
m_right = std::move(child);
m_right->parent = this;
;
你会像下面这样使用它:
int main()
auto tree = std::make_unique<Node>();
auto subtree = std::make_unique<Node>();
subtree->right(std::make_unique<Node>());
tree->right(std::make_unique<Node>());
tree->left(std::move(subtree));
return 0;
我自己对unique_ptr
还很陌生,希望有人能进一步纠正我。
顺便说一句,不要使用以_
开头的名称作为您的标识,它们是保留的。
【讨论】:
"TW 不要使用以 _ 开头的名称作为您的标识,它们是保留的。"有时。 What are the rules about using an underscore in a C++ identifier? 我不使用它们,因为如果我不小心违反了其中一条规则,我不想要惊喜。 嗯,这也是我的精神。【参考方案2】:我认为你不能使用:
Node(Node _left, Node _right, Node _parent);
这将不允许逐个节点构建树。相反,使用:
Node(Node* _left, Node* _right, Node* _parent);
这样,您可以使用以下方法创建第一个节点:
Node firstNode(nullptr, nullptr, nullptr);
从那里,您可以构建其他节点。
构建一个简单的树,三个节点如下
N1
/ \
N2 N3
你可以使用:
Node* N1 = new Node(nullptr, nullptr, nullptr);
Node* N2 = new Node(nullptr, nullptr, N1);
Node* N3 = new Node(nullptr, nullptr, N1);
N1->left = N2; // Use the equivalent member function.
N1->right = N3;
【讨论】:
在构造N1
、N2
和N3
时最好使用std::unique_ptr<Node>
甚至std::make_unique<Node>()
,然后将std::move()
N2
和N3
转换为@9876543 N1->right
。此外,_left
和 _right
构造函数参数也应该是 std::unique_ptr<Node>
嘿,你是怎么建造那棵树的?我可能会尝试记住如何以这种方式提供更好的问题。
@Dogunboundhounds,你的意思是 ASCII 艺术中的树?
@RSahu 是的。我怎么做?在 *** 编辑器中。
@Dogunboundhounds,就像写代码一样。使用字符 /
和 \
创建连接。不习惯有点乏味,但习惯了就不会那么糟糕了。【参考方案3】:
我相信您想公开父母、左右孩子。至少,这就是我一直使用struct
来实现我的节点的方式:
struct Node
Node(std::unique_ptr<Node> _parent = nullptr,
std::unique_ptr<Node> _left = nullptr, std::unique_ptr<Node> _right = nullptr) : parent(_parent), left(_left), right(_right)
std::unique_ptr<Node> parent;
std::unique_ptr<Node> left;
std::unique_ptr<Node> right;
;
如果我错了,请有人纠正我。
【讨论】:
必然一个Node
的parent
将是另一个Node
的left
或right
。如果有两个指向它的指针,则不是一个非常唯一的指针。 OP 有这部分权利。
@user4581301 啊,这是有道理的。我从来没有真正使用过std::unique_ptr
,我一直使用std::shared_ptr
,并错误地认为可以以相同的方式使用unique和shared。
用简单的英语描述各种智能指针用途的好答案:***.com/a/30143936/4581301。该问题的第一个答案更详细地说明了如何以及何时使用。
@user4581301 感谢您提供链接。我的教授向我展示了如何使用std::shared_ptr
构建节点,所以如果我们用共享替换所有唯一节点,那会是不好的做法吗?或者如果它完成了工作,这是否可以接受?
youtube.com/watch?v=JfmTagWcqoE&t=1864s 转至 22:41。这就是我发布这个问题的原因以上是关于使用唯一指针将节点添加到树的主要内容,如果未能解决你的问题,请参考以下文章