Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/132.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 复制二叉树的构造函数C++;_C++_Copy Constructor_Binary Tree - Fatal编程技术网

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);