我正在使用符号计算器。但是为了给出一个可验证的小例子,我把它分解为下面的例子,起初看起来可能很奇怪。
我有一个点{1,4,4,8,5,7}的列表,我会迭代。我在每次迭代中都读了两点。
我希望这段代码能做的是:
迭代1:没有树,所以我们创建一个。我们对4进行了参考。
4
/
1
迭代2: 8大于最后一个引用(4)。所以我们制作
8
/
3
4岁的右孩,并在8
上保留参考 4
/ \
1 8
/
3
迭代3: 7小于最后一个引用(8)所以我们返回直到找到小于4的数字(或到达根目录)。然后我们创建节点
7
\
5
并将最后一个引用添加为左子项。
7
/ \
4 5
/ \
1 8
/
3
请注意:我这里并不关心特殊情况等。我很积极,一旦我开始工作,我就可以自己解决这个问题。
这是我的树类:
#ifndef NODE_H
#define NODE_H
#include <memory>
#include <string>
template<typename T>
class Node : public std::enable_shared_from_this< Node<T> >{
public:
typedef std::shared_ptr< Node<T> > NodePtr;
typedef std::weak_ptr< Node<T> > NodeWPtr;
T data;
NodePtr left, right;
NodeWPtr parent;
Node(){}
Node(const T& data) : data(data){}
Node(const T& data, NodeWPtr parent) : data(data), parent(parent){}
Node(const T& data, NodeWPtr parent, NodePtr& left) : data(data), parent(parent), left(left){
left->parent = this->shared_from_this();
}
Node(const Node& n) : data(n.data), left(n.left), right(n.right){}
Node& operator=(const Node&) = delete;
~Node() = default;
NodePtr findRoot(){
if( parent.lock() ){
return parent.lock()->findRoot();
}
return this->shared_from_this();
}
void print(int indent=0){
std::cout << data << std::endl;
std::cout << std::string(2*indent+2, '-') << "L: ";
if( left ){
left->print(indent+1);
}
std::cout << std::endl;
std::cout << std::string(2*indent+2, '-') << "R: ";
if( right ){
right->print(indent+1);
}
if( indent==0 ) std::cout << std::endl;
}
};
#endif // NODE_H
这是我的main.cpp
#include <iostream>
#include <vector>
#include "Node.h"
int main(){
typedef std::shared_ptr< Node<int> > NodePtr;
NodePtr last;
std::vector<int> list {1, 4, 3, 8, 5, 7};
for( unsigned int i = 0; i < list.size(); i += 2 ){
if( !last ){
last = std::make_shared< Node<int> >(Node<int>(list.at(i+1)));
last->left = std::make_shared< Node<int> >(Node<int>(list.at(i), last));
continue;
}
if( list.at(i+1) >= last->data ){
NodePtr newNode = std::make_shared< Node<int> >(Node<int>(list.at(i+1)));
newNode->left = std::make_shared< Node<int> >(Node<int>(list.at(i)));
last->right = newNode;
newNode->parent = last;
newNode->findRoot()->print();
last = newNode;
last->findRoot()->print();
}else{
while( !last->parent.expired() && last->data < list.at(i+1) ){
last = last->parent.lock();
}
NodePtr newNode = std::make_shared< Node<int> >(Node<int>(list.at(i+1)));
newNode->right = std::make_shared< Node<int> >(Node<int>(list.at(i)));
newNode->left = last;
last->parent = newNode;
last = newNode;
}
}
last->findRoot()->print();
}
当我在第二次迭代中复制它时,不知何故4-1分支被删除了。它在第一次印刷中仍然存在,但在复制后,它已经消失了。
答案 0 :(得分:1)
问题在于以下一行
newNode->parent = last;
newNode->findRoot()->print();
last = newNode;
最初,只有shared_ptr last
指向节点4.将newNode
分配给last
后,不再有指向节点4的shared_ptr。这导致节点8中的weak_ptr parent
到期。因此,当您调用last->findRoot()
(此处为节点8)时,它无法返回节点4.
您的数据结构可确保除了根目录之外的每个节点至少由1个shared_ptr(其父节点)指向。因此,您需要手动将shared_ptr保存到根节点。