我正在开发二进制搜索树(BST)程序。根据赋值的要求,用户加载文本文件以构造树。如果用户想要,他们可以通过加载新的文本文件来创建新树。加载新文本文件应该销毁旧树。
为了满足此要求,我创建新树的方法readNewFile()
首先检查树是否已存在。如果是,它将在树上运行析构函数。但是,我需要创建一个存在于readNewFile()
范围之外的新树,以便可以全局访问它。这可能吗?如果是这样,你能解释一下吗?
我的缩减代码:
int main() {
//BST
BST rootTree;
readNewFile(rootTree);
readNewFile(rootTree);
return 0;
}
void readNewFile(BST& tree) {
ifstream inFile;
string fileName;
// if tree was previously filled, destroy it
if (tree.rootPtr() != NULL) {
tree.~BST();
BST tree = new BST();
}
cout << "\nEnter file to load: ";
cin.ignore();
getline(cin, fileName);
cout << "Opening file " << fileName << endl;
inFile.open(fileName.c_str(), ios::in);
// Populates tree... //
}
析构函数(在BST.hpp中):
BST::~BST() {
destroyTree(root);
}
void BST::destroyTree(TreeNode*& treePtr) {
if (treePtr != NULL) {
destroyTree(treePtr->leftChildPtr);
destroyTree(treePtr->rightChildPtr);
delete treePtr;
}
}
这会返回一个段错误,这是有意义的,因为树被破坏了。但是,有没有办法可以创建一个新树,其范围与被破坏的BST rootTree
相同?
答案 0 :(得分:1)
实现此要求的一种方法是在del()
类中使用名为BST
的方法。它所做的就是删除树的所有节点,但不删除根指针。这是指向根节点的指针。调用del()
后,您可以开始创建新树。伪代码看起来像这样:
// if tree was previously filled, destroy it
if (tree.rootPtr() != NULL) {
tree.del()
}
// read the input file
// Start inserting the new nodes
答案 1 :(得分:1)
首先:代码出了什么问题。
正如您已经指出的那样,如果树被破坏,您将无法再次使用它。在这种情况下,它是双坏的:通过调用BST
中readNewFile()
上的析构函数,你导致析构函数被调用两次 - 一次是在你明确调用它时,第二次是main()
中的本地实例超出范围。 This is bad.
现在关于如何解决它:
最简单的方法是将rootTree
声明为main()
内的指针,然后使readNewFile()
将指针指针作为参数。 readNewFile()
会破坏指针指向的现有树,然后将指针重置为指向它创建的新树。简单。
更好的设计是使readNewFile()
成为BST
的成员函数。然后main()
应该构建一个新的BST
并调用该实例的readNewFile()
。
答案 2 :(得分:0)
你永远不会直接调用析构函数,除非你很清楚你正在做什么。然后,它通常是因为它是使用placement new创建的。此外,“T t = new T;”没有意义,将指针指向T.我的猜测是你在这里复制Javaism,但这两种语言的对象模型太不同了。