我有一个学校作业,要求我用c ++创建一个二叉树,完成所有常用的重载操作符(=,==,!=,copy,destroy等)。我目前正在努力编写复制构造函数方法。在这个赋值中,我被要求不要在operator =或copy构造函数方法中使用二叉树类的insert方法。这是二叉树类头文件:
#ifndef BINTREE_H
#define BINTREE_H
#include <iostream>
#include "nodedata.h"
using namespace std;
class BinTree
{
public:
BinTree(); // constructor
BinTree(const BinTree &); // copy constructor, calls copyHelper
~BinTree(); // destructor, calls makeEmpty
bool insert(NodeData*); // insert method, inserts new nodes
bool isEmpty() const; // true if tree is empty, otherwise false
private:
struct Node
{
NodeData* data; // pointer to data object
Node* left; // left subtree pointer
Node* right; // right subtree pointer
};
Node* root; // root of the tree
Node& copyHelper(const Node*); // copies the tree recursively
void makeEmpty(Node*); // deletes nodes recursively
};
#endif
以下是我到目前为止复制构造函数的内容:
BinTree::BinTree(const BinTree &otherTree)
{
root = copyHelper(otherTree.root); // 1
}
Node& BinTree::copyHelper(const Node* other) // 2
{
if(other == NULL)
{
return NULL; // 3
}
Node newNode; // 4
if(other.data == NULL)
{
newNode.data = NULL; // 5
}
else
{
NodeData newNodeData(*other->data); // 6
newNode.data = newNodeData; // 7
}
newNode.left = copyHelper(other.left); // 8
newNode.right = copyHelper(other.right); // 9
return newNode; // 10
}
这导致各种编译错误,我不理解它们中的任何一个。这就是我认为应该发生的事情: •概述:整个树将以递归方式从头开始复制。当每个节点返回到其上方的节点时,每个节点应该已经包含所有子节点(如果存在)的数据和链接。
以下是我现有的问题:
一般来说,我认为我的概念已经失效,但语法完全杀了我。我昨天花了整整一天的时间在这上面,我准备承认失败并寻求帮助。你们在我的代码中看到了什么错误,我该如何修复它们?
答案 0 :(得分:1)
Node& copyHelper(const Node*); // copies the tree recursively
一定是参考吗?它看起来应该是 Node * 。
在copyHelper
的声明中,Node
类型嵌套在BinTree
中,但您未能实现此目的。它应该是
BinTree::Node* BinTree::copyHelper(const BinTree::Node* other)
答案 1 :(得分:1)
这一行:
Node newNode; // 4
在堆栈上分配节点。当函数返回时,节点不再有效。它已超出范围。如果另一个函数调用没有重写堆栈,它可能会工作一段时间。
您需要在节点上执行新操作。
答案 2 :(得分:0)
->
取消引用指针。它是*pointer.member
的快捷方式。new
在堆上创建对象并返回指针 - 它不会创建指针。每次在堆上创建对象时,都必须使用new
。Node * newNode = new Node;
将指向新创建的Node的指针分配给newNode。 Node *
是指向对象的指针,而不是指向指针的指针,它将是Node **
。您无法执行Node newNode = new Node;
,因为Node *
(指针)无法转换为Node
(对象)。.
代替->
。答案 3 :(得分:0)
经过多次烦恼和拉扯头发之后,我重写了我的复制构造函数并将其编译完毕。它可能仍然存在错误,但我现在感觉好多了,部分归功于此处发布的提示。再次感谢!这是修改后的代码:
BinTree::BinTree(const BinTree &otherTree)
{
root = copyHelper(otherTree.root); // Starts recursively copying Nodes from
// otherTree, starting with root Node.
}
BinTree::Node* BinTree::copyHelper(const Node* other) // Needed BinTree at beginning
// due to nested Node struct
// in BinTree class.
{
if(other == NULL)
{
return NULL; // If there's no Node to copy, return NULL.
}
Node* newNode = new Node; // Dynamically allocated memory will remain after
// function is no longer in scope. Previous newNode
// object here was destroyed upon function return.
if(other->data == NULL) // Other is a pointer to data, which is also a pointer.
// -> dereferences other, and provides the item at the
// memory address which other normally points to. It
// just so happens that since data is a pointer itself,
// it can still be treated as such. I had stupidly been
// attempting to use . instead of ->, because I was afraid
// the -> would dereference data as well. If I actually
// wanted to DO this, I'd have to use *other->data, which
// would dereference all of other->data, as if there were
// parenthesis around it like this: *(other->data).
// Misunderstanding this was the source of most of the
// problems with my previous implementation.
{
newNode->data = NULL; // The other Node doesn't contain data,
// so neither will this one.
}
else
{
NodeData* newNodeData = new NodeData; // This needed to be dynamically
// allocated as well.
*newNodeData = *other->data; // Copies data from other node.
newNode->data = newNodeData;
}
newNode->left = copyHelper(other->left); // Recursive call to left node.
newNode->right = copyHelper(other->right); // Recursive call to right node.
return newNode; // Returns after child nodes have been linked to newNode.
}