C++ 复制二叉树的构造函数C++;
我有一个具有以下定义的树类:C++ 复制二叉树的构造函数C++;,c++,copy-constructor,binary-tree,C++,Copy Constructor,Binary Tree,我有一个具有以下定义的树类: class Tree { Tree(); private: TreeNode *rootPtr; } TreeNode表示一个节点,具有数据leftPtr和rightPtr 如何使用复制构造函数创建树对象的副本?我想做一些类似的事情: Tree obj1; //insert nodes Tree obj2(obj1); //without modifying obj1. 感谢您的帮助 伪代码: struct Tree { Tree(Tree con
class Tree {
Tree();
private:
TreeNode *rootPtr;
}
TreeNode表示一个节点,具有数据leftPtr和rightPtr
如何使用复制构造函数创建树对象的副本?我想做一些类似的事情:
Tree obj1;
//insert nodes
Tree obj2(obj1); //without modifying obj1.
感谢您的帮助 伪代码:
struct Tree {
Tree(Tree const& other) {
for (each in other) {
insert(each);
}
}
void insert(T item);
};
具体示例(了解更改树的行走方式很重要,但会影响演示复制计算器的工作方式,并且可能会让人在这里做太多作业):
#包括
#包括
#包括
模板
树状结构{
类型数据;
TreeNode*左;
TreeNode*对;
明确的
TreeNode(Type const&value=Type()):数据(value),左(0),右(0){}
};
模板
结构树{
typedef树节点;
树():根(0){}
树(树常数和其他):根(0){
std::向量剩余;
Node const*cur=other.root;
while(cur){
插入(当前->数据);
如果(当前->右侧){
剩余。向后推(当前->右侧);
}
如果(当前->左){
cur=cur->left;
}
else if(剩余的.empty()){
打破
}
否则{
cur=剩余的.back();
剩余的。向后弹出();
}
}
}
~Tree(){
std::向量剩余;
节点*cur=根;
while(cur){
节点*左=当前->左;
如果(当前->右侧){
剩余。向后推(当前->右侧);
}
删除cur;
如果(左){
cur=左;
}
else if(剩余的.empty()){
打破
}
否则{
cur=剩余的.back();
剩余的。向后弹出();
}
}
}
无效插入(类型常量和值){
//次优插入
Node*new_root=新节点(值);
新建根->左=根;
根=新根;
}
//包含简单op=比不允许更容易
//或者使用编译器提供的错误
无效交换(树和其他){std::swap(root,other.root);}
树和运算符=(树复制){swap(复制);返回*this;}
朋友
ostream和Operator(左){
cur=cur->left;
}
else if(剩余的.empty()){
打破
}
否则{
cur=剩余的.back();
剩余的。向后弹出();
}
}
返回s;
}
私人:
节点*根;
};
int main(){
使用名称空间std;
树a;
a、 插入(5);
a、 插入(28);
a、 插入(3);
a、 插入(42);
cout这取决于您是否需要副本。假设是深度副本,您需要能够复制挂在TreeNode
对象上的“叶子”上的任何内容;因此理想情况下,功能应该位于TreeNode
(除非Tree
是TreeNode
的一个朋友类,您设计该类是为了深入了解其实现,当然通常是这样;-)。假设类似于…:
template <class Leaf>
class TreeNode {
private:
bool isLeaf;
Leaf* leafValue;
TreeNode *leftPtr, *rightPtr;
TreeNode(const&Leaf leafValue);
TreeNode(const TreeNode *left, const TreeNode *right);
...
模板
三烯类{
私人:
布尔岛;
叶*叶值;
TreeNode*左PTR,*右PTR;
TreeNode(常数和叶值);
树节点(常数树节点*左,常数树节点*右);
...
然后你可以加上一个
public:
TreeNode<Leaf>* clone() const {
if (isLeaf) return new TreeNode<Leaf>(*leafValue);
return new TreeNode<Leaf>(
leftPtr? leftPtr->clone() : NULL,
rightPtr? rightPtr->clone() : NULL,
);
}
公共:
TreeNode*克隆()常量{
如果(isLeaf)返回新的树节点(*leafValue);
返回新树节点(
leftPtr?leftPtr->clone():NULL,
rightPtr?rightPtr->clone():空,
);
}
如果Tree
负责这一级别的功能(作为朋友类),那么显然您将拥有完全相同的功能,但节点将被克隆为显式参数。两个基本选项:
如果您有可用的迭代器,您可以简单地迭代树中的元素并手动插入每个元素,如R.Pate所述。如果您的树类没有采取明确的措施来平衡树(例如AVL或红黑旋转),那么您将以这种方式有效地得到一个节点链接列表(也就是说,所有左边的子指针都将为空)。如果您要平衡树,您将有效地执行两次平衡工作(因为您必须在要复制的源树上找到平衡)
一个更快但更混乱、更容易出错的解决方案是,通过对源树结构进行广度优先或深度优先遍历,自上而下地构建副本。您不需要任何平衡旋转,最终将得到相同的节点拓扑。当类的指针指向动态分配的内存时,在复制该类的构造函数您需要为新创建的对象分配内存。然后您需要使用其他指针指向的任何对象初始化新分配的内存。下面是一个示例,说明如何处理具有动态分配内存的类:
class A
{
int *a;
public:
A(): a(new int) {*a = 0;}
A(const A& obj): a(new int)
{
*a = *(obj.a);
}
~A() {delete a;}
int get() const {return *a;}
void set(int x) {*a = x;}
};
您可以尝试(未经测试)
这是我在二叉树中使用的另一个示例。
在本例中,节点和树是在单独的类中定义的,而copyHelper
递归函数有助于copyTree
函数。代码不完整,我只尝试了理解函数如何实现所需的内容
copyHelper:
void copyHelper( BinTreeNode<T>* copy, BinTreeNode<T>* originalNode ) {
if (originalTree == NULL)
copy = NULL;
else {
// set value of copy to that of originalTree
copy->setValue( originalTree->getValue() );
if ( originalTree->hasLeft() ) {
// call the copyHelper function on a newly created left child and set the pointers
// accordingly, I did this using an 'addLeftChild( node, value )' function, which creates
// a new node in memory, sets the left, right child, and returns that node. Notice
// I call the addLeftChild function within the recursive call to copyHelper.
copyHelper(addLeftChild( copy, originalTree->getValue()), originalTree->getLeftChild());
}
if ( originalTree->hasRight() ) { // same with left child
copyHelper(addRightChild(copy, originalTree->getValue()), originalTree->getRightChild());
}
} // end else
} // end copyHelper
用法:
Tree obj2 = obj2->copy(obj1);
<>我希望这能帮助某人。< /P>是这个作业吗?请把它标记为这样。谢谢!不像java中C++默认的是私有的,所以构造函数必须是公共的,否则你不能创建Objisti。认为这个人想要一个深拷贝是安全的。但是指出这个区别是很好的。第一个选项可能更安全,但是MO。构造O(N log(N))的成本很高,而第二个选项仅仅是O(N),即使在公共接口中没有特定的迭代器类型,他也不难按照自己的喜好(甚至递归地)遍历树@R.Pate:同意——我只是想鼓励他不要按顺序遍历,因为这样会产生不平衡的效果。我喜欢这个解决方案。但我遇到的问题是rootPtr是树类的私有数据成员。有一个返回rootPtr的get函数可以吗?没有rootPtr我不知道如何遍历
void copyHelper( BinTreeNode<T>* copy, BinTreeNode<T>* originalNode ) {
if (originalTree == NULL)
copy = NULL;
else {
// set value of copy to that of originalTree
copy->setValue( originalTree->getValue() );
if ( originalTree->hasLeft() ) {
// call the copyHelper function on a newly created left child and set the pointers
// accordingly, I did this using an 'addLeftChild( node, value )' function, which creates
// a new node in memory, sets the left, right child, and returns that node. Notice
// I call the addLeftChild function within the recursive call to copyHelper.
copyHelper(addLeftChild( copy, originalTree->getValue()), originalTree->getLeftChild());
}
if ( originalTree->hasRight() ) { // same with left child
copyHelper(addRightChild(copy, originalTree->getValue()), originalTree->getRightChild());
}
} // end else
} // end copyHelper
Tree* copy( Tree* old ) {
Tree* tree = new Tree();
copyHelper( tree->root, oldTree->getRoot() );
// we just created a newly allocated tree copy of oldTree!
return tree;
} // end copy
Tree obj2 = obj2->copy(obj1);