我在C ++中创建了一个简单的二叉树结构:
template <class T>
struct MyBinaryTree {
T val;
BinaryTree<T>* left;
BinaryTree<T>* right;
BinaryTree<T>(T v, BinaryTree<T>* l, BinaryTree<T>* r)
: val(v), left(l), right(r) {}
};
我想编写一个创建二叉树并返回它的函数。不幸的是,这个结构包含指针。因此,如果我在堆栈上返回二叉树,则指针将变得无关紧要。
我有办法返回二叉树结构吗?
答案 0 :(得分:2)
正如其他人所说,您需要利用动态分配。使用new
时,您通常需要遵守Rule of Three, Four, or Five。这意味着您需要决定销毁,复制构造,分配,移动构造和移动分配应如何表现,并实施它们。通常,对于容器,您需要深层复制语义。即使你使用智能指针使破坏变得简单,你也需要做更多的事情才能使副本更深。
但是,不一定需要new
来应用动态内存分配。例如,您可以使用list<>
来代表left
和right
,而这样做可以自动为您提供深层复制语义:
template <typename T>
class MyBinaryTree {
T val_;
std::list< MyBinaryTree<T> > left_;
std::list< MyBinaryTree<T> > right_;
template <typename U>
friend MyBinaryTree<U> MakeMyBinaryTree (U v,
MyBinaryTree<U> *l = 0,
MyBinaryTree<U> *r = 0) {
MyBinaryTree<U> t;
t.val_ = v;
if (l) t.left_.push_back(*l);
if (r) t.right_.push_back(*r);
return t;
}
public:
MyBinaryTree<T>* left () { return left_.empty() ? 0 : &*left_.begin(); }
MyBinaryTree<T>* right () { return right_.empty() ? 0 : &*right_.begin(); }
T & val () { return val_; }
};
MyBinaryTree<int> make_a_tree ()
{
MyBinaryTree<int> n1 = MakeMyBinaryTree(1);
MyBinaryTree<int> n3 = MakeMyBinaryTree(3);
return MakeMyBinaryTree(2, &n1, &n3);
}
而不是list<>
,您可以使用Boost.Optional,或者如果您可以使用C ++ 14,std::optional
。
答案 1 :(得分:1)
您创建了一个动态容器 - 例如。一个,在运行时构建的。在这种结构的情况下,您必须动态分配它们并使用指针来引用它们。那就是:
MyBinaryTree * BuildSimpleTree()
{
BinaryTree<int> * node1 = new BinaryTree(0, nullptr, nullptr);
BinaryTree<int> * node2 = new BinaryTree(0, nullptr, nullptr);
return new MyBinaryTree<int>(0, node1, node 2);
}
MyBinaryTree * tree = BuildSimpleTree();
动态分配要求背后的原因是当您离开函数或方法时,所有本地静态分配的对象(例如,驻留在堆栈而不是堆上)会自动销毁。但是,为了使树正常工作,它的所有子节点(以及递归子节点)在从函数返回后仍然保持活动状态,因此必须动态分配它们。
您必须记住释放已分配类的所有实例。这可以手动或自动递归完成 - 在BinaryTree和MyBinaryTree dtors中。
如果你能够使用C ++ 11编译你的代码,总会有一个选项来使用移动语义 - 你将能够按值返回树,同时保持代码快速和内存效率。此解决方案如下所示:
template <class T>
struct MyBinaryTree
{
T val;
BinaryTree<T>* left;
BinaryTree<T>* right;
BinaryTree<T>(T v, BinaryTree<T>* l, BinaryTree<T>* r)
: val(v), left(l), right(r)
{
}
BinaryTree<T>(BinaryTree<T> && r)
{
val = r.val;
left = r.left;
right = r.right;
}
};
然后,您可以按值返回树(但仍然动态构建节点):
MyBinaryTree BuildTree()
{
auto left = new BinaryTree<int>(0, nullptr, nullptr);
auto right = new BinaryTree<int>(0, nullptr, nullptr);
MyBinaryTree<int> result(0, left, right);
return result;
}
答案 2 :(得分:1)
您需要动态分配数据。例如创建
2
/ \
1 3
使用您的结构,您将执行以下操作:
MyBinaryTree<int>* getTestStructure(){
MyBinaryTree<int> *root = new MyBinaryTree<int>(2);
MyBinaryTree<int> *leftChild = new MyBinaryTree<int>(1);
MyBinaryTree<int> *rightChild = new MyBinaryTree<int>(3);
root.left = leftChild;
root.right = rightChild;
return root;
}