二叉树运算符深拷贝
Binary tree operator deep copy
我正在尝试使用“=”运算符进行深拷贝,但按照我的写法,它似乎是浅拷贝,但我不明白为什么会这样。
bs2 还添加了 "q" 所以我可以理解它做了浅拷贝
为什么是浅拷贝,我以为是深拷贝。
如何将其更改为深拷贝?
here is what I tried:
BSNode& BSNode::operator=(const BSNode& other)
{
if (this == &other) // tries to copy the object to itself
{
return *this;
}
delete _left;
_left = other._left;
delete _right;
_right = other._right;
return *this;
}
class BSNode
{
public:
BSNode(std::string data);
BSNode(const BSNode& other);
~BSNode();
BSNode& operator=(const BSNode& other);
//some more functions...
private:
std::string _data;
BSNode* _left;
BSNode* _right;
int _count; count the times an element appears in the tree
};
BSNode* bs1 = new BSNode("d");
bs1->insert("d");
bs1->insert("b");
BSNode* bs2 = new BSNode("1");
bs2 = bs1;
bs1->insert("q");
bs2->printNodes(bs2);//bs2 also added "q"
```
bs2 also added "q" so I can understand it did shallow copy
why is it shallow copy, I expected it to be deep-copying.
how can I change it to deep copy?
why is it shallow copy
因为如果您将 this
的指针成员指定为指向与另一个实例所指向的对象相同的对象,那么您就进行了浅拷贝。
为了拥有树的深层副本,您必须为副本创建节点。如果没有重复的节点集,则不存在树的重复(深)副本。您的赋值运算符中没有任何地方创建任何节点。
您需要实际构建新节点,而不是(只是)删除旧节点。如果一棵树由五个节点组成,而你从不构造任何新节点,那么之后就不可能有两棵五个节点的树。
你的复制赋值运算符应该完全代表一棵新树的构造。在这种情况下,您可以利用复制构造函数(无论如何您都应该通过三规则获得):
BSNode::BSNode(const BSNode& other) {
if(other._left){
_left = new BSNode(*other._left);
}
if(other._right) {
_right = new BSNode(*other._right);
}
}
BSNode& BSNode::operator=(const BSNode& other)
{
if (this == &other) // tries to copy the object to itself
{
return *this;
}
delete _left;
if(other._left){
_left = new BSNode(*other._left);
}
delete _right;
if(other._right) {
_right = new BSNode(*other._right);
}
return *this;
}
这是一个比较,显示了与实际的对象分配相比,您的错误调用只是分配指针。我假设您的构造函数格式正确,并使成员成为私有成员 public,因为您没有包含我快速测试它所需的所有代码。
int main(){
// bad
BSNode* ap = new BSNode("a");
ap->_left = new BSNode("al");
BSNode* bp = ap;
bp->_left = new BSNode("bl");
std::cout << ap->_left->_data << std::endl;
// good
BSNode a("a");
a._left = new BSNode("al");
BSNode b(a);
b._left = new BSNode("bl");
std::cout << a._left->_data << std::endl;
}
在为递归数据结构编写算法时考虑递归。
首先定义你的概念:
Clone of a node A is:
Empty if A is empty, or
A new node whose data is the copy of A's data, left is Clone of A's left node, and right is Clone of A's right node otherwise.
这可以翻译成辅助方法:
BSNode* clone_node(const BSNode* src) {
if (src == nullptr) return nullptr;
BSNode* clonedNode = new BSNode(src.data);
clonedNode.left = clone_node(src.left);
clonedNode.right = clone_node(src.right);
return clonedNode;
}
现在您可以这样表达您的operator=
:
BSNode& BSNode::operator=(const BSNode& other)
{
if (this == &other) // tries to copy the object to itself
{
return *this;
}
this->data = other.data;
delete this->left;
delete this->right;
this->left = clone_node(other.left);
this->right = clone_node(other.right);
return *this;
}
但是,如果您的左(或右)节点不是 nullptr
,您可以重用它们(而不是分配新节点)。编写另一个辅助方法:
void clone_to(BSNode*& dest, const BSNode* src) {
if (dest != nullptr && src != nullptr) {
*dest = *src;
}
else {
delete dest;
dest = clone_node(src);
}
}
现在你可以写你的最终版本了 operator=
:
BSNode& BSNode::operator=(const BSNode& other)
{
if (this == &other) // tries to copy the object to itself
{
return *this;
}
this->data = other.data;
clone_to(this->left, other.left);
clone_to(this->right, other.right);
return *this;
}
我正在尝试使用“=”运算符进行深拷贝,但按照我的写法,它似乎是浅拷贝,但我不明白为什么会这样。 bs2 还添加了 "q" 所以我可以理解它做了浅拷贝 为什么是浅拷贝,我以为是深拷贝。 如何将其更改为深拷贝?
here is what I tried:
BSNode& BSNode::operator=(const BSNode& other)
{
if (this == &other) // tries to copy the object to itself
{
return *this;
}
delete _left;
_left = other._left;
delete _right;
_right = other._right;
return *this;
}
class BSNode
{
public:
BSNode(std::string data);
BSNode(const BSNode& other);
~BSNode();
BSNode& operator=(const BSNode& other);
//some more functions...
private:
std::string _data;
BSNode* _left;
BSNode* _right;
int _count; count the times an element appears in the tree
};
BSNode* bs1 = new BSNode("d");
bs1->insert("d");
bs1->insert("b");
BSNode* bs2 = new BSNode("1");
bs2 = bs1;
bs1->insert("q");
bs2->printNodes(bs2);//bs2 also added "q"
```
bs2 also added "q" so I can understand it did shallow copy
why is it shallow copy, I expected it to be deep-copying.
how can I change it to deep copy?
why is it shallow copy
因为如果您将 this
的指针成员指定为指向与另一个实例所指向的对象相同的对象,那么您就进行了浅拷贝。
为了拥有树的深层副本,您必须为副本创建节点。如果没有重复的节点集,则不存在树的重复(深)副本。您的赋值运算符中没有任何地方创建任何节点。
您需要实际构建新节点,而不是(只是)删除旧节点。如果一棵树由五个节点组成,而你从不构造任何新节点,那么之后就不可能有两棵五个节点的树。
你的复制赋值运算符应该完全代表一棵新树的构造。在这种情况下,您可以利用复制构造函数(无论如何您都应该通过三规则获得):
BSNode::BSNode(const BSNode& other) {
if(other._left){
_left = new BSNode(*other._left);
}
if(other._right) {
_right = new BSNode(*other._right);
}
}
BSNode& BSNode::operator=(const BSNode& other)
{
if (this == &other) // tries to copy the object to itself
{
return *this;
}
delete _left;
if(other._left){
_left = new BSNode(*other._left);
}
delete _right;
if(other._right) {
_right = new BSNode(*other._right);
}
return *this;
}
这是一个比较,显示了与实际的对象分配相比,您的错误调用只是分配指针。我假设您的构造函数格式正确,并使成员成为私有成员 public,因为您没有包含我快速测试它所需的所有代码。
int main(){
// bad
BSNode* ap = new BSNode("a");
ap->_left = new BSNode("al");
BSNode* bp = ap;
bp->_left = new BSNode("bl");
std::cout << ap->_left->_data << std::endl;
// good
BSNode a("a");
a._left = new BSNode("al");
BSNode b(a);
b._left = new BSNode("bl");
std::cout << a._left->_data << std::endl;
}
在为递归数据结构编写算法时考虑递归。
首先定义你的概念:
Clone of a node A is:
Empty if A is empty, or
A new node whose data is the copy of A's data, left is Clone of A's left node, and right is Clone of A's right node otherwise.
这可以翻译成辅助方法:
BSNode* clone_node(const BSNode* src) {
if (src == nullptr) return nullptr;
BSNode* clonedNode = new BSNode(src.data);
clonedNode.left = clone_node(src.left);
clonedNode.right = clone_node(src.right);
return clonedNode;
}
现在您可以这样表达您的operator=
:
BSNode& BSNode::operator=(const BSNode& other)
{
if (this == &other) // tries to copy the object to itself
{
return *this;
}
this->data = other.data;
delete this->left;
delete this->right;
this->left = clone_node(other.left);
this->right = clone_node(other.right);
return *this;
}
但是,如果您的左(或右)节点不是 nullptr
,您可以重用它们(而不是分配新节点)。编写另一个辅助方法:
void clone_to(BSNode*& dest, const BSNode* src) {
if (dest != nullptr && src != nullptr) {
*dest = *src;
}
else {
delete dest;
dest = clone_node(src);
}
}
现在你可以写你的最终版本了 operator=
:
BSNode& BSNode::operator=(const BSNode& other)
{
if (this == &other) // tries to copy the object to itself
{
return *this;
}
this->data = other.data;
clone_to(this->left, other.left);
clone_to(this->right, other.right);
return *this;
}