我有这个删除功能,它将BST中的节点作为参数来删除它。在做任何事情之前,它会检查三个案例:
前两种情况有效,但最后两种情况并非如此。这种情况的代码如下
AccNode* smallest = pointer->getRight();
bool foundSmallest = false;
// Find the smallest node in the right branch
while (foundSmallest == false) {
if (smallest->getLeft() == NULL && smallest->getRight() == NULL) {
foundSmallest = true;
} else {
if (smallest->getLeft() == NULL && smallest->getRight() != NULL) {
smallest = smallest->getRight();
} else {
smallest = smallest->getLeft();
}
}
}
// Replace the node we want to delete with the data in
// smallest node we found and delete smallest node in that tree
pointer->setData(smallest->getData());
delete smallest;
为了进一步调试,Xcode有一些很酷的工具可以让你看到树,我发现了一些非常有趣的东西。在我们到达行delete smallest;
之前,树中的最小节点看起来像这样
删除行后,它看起来像这样
那么这里发生了什么?我是否正在用我使用指针的方式弄乱一些东西?
编辑:我刚刚意识到了什么。在删除树上的图像中,在折叠的部分中,右节点不再是NULL并且现在具有值。我打开它,它是我们想要从头开始删除的节点的整个右分支(所以原始指针的右分支)。所以我觉得我现在肯定对指针做错了。任何关于它是什么的线索?
答案 0 :(得分:2)
你忘了指向最小的指针(在最小的父节点中)。这使得指针成为悬空指针,指针指向已经释放的内存。调试器显示这种内存的任意内容,在很多情况下就是之前的内容。
您需要跟踪父节点。
此外,当当前逻辑不能向左分支并且右分支时,当前逻辑分支正确。但这会导致一个价值更高的节点,包括其所有孩子。所以这个逻辑是不合适的。
在父项中复制数据,删除和清空指针的替代方法是重新排列树(将最小的节点移动到您确实要删除的节点的位置)然后只删除您真正想要的节点删除。这有两个优点,即通常做较少的工作,并保持节点的其他指针有效。
Niklaus Wirth的书“Algorithms + Data Structures = Programs”对此非常宝贵。我读了基于Pascal的原版。我相信现在有一个基于Oberon的免费电子版。
一般建议:在现代C ++中,使用nullptr
代替宏NULL
是个好主意。它通常更安全。
此外,而不是
foundSmallest == false
只是(1)写
not foundSmallest
或
!foundSmallest
(1)至少有一个不完全符合标准的编译器,您必须包含<iso646.h>
标头才能使用保留字and
,or
和not
作为运营商。但是,这可以通过命令行中的强制include指令来完成。它不需要在代码中显示。
功能
答案 1 :(得分:0)
删除smallest
所占用的内存后,再无法读取内存。这只是垃圾数据。它可能有意义,它可能没有,但不保证任何东西。
在算术上,正如Cheers指出的那样,您忘记将smallest
节点作为其父节点的子节点删除。换句话说,它的原始部分仍然指向它。您可以通过跟踪parent
节点来解决此问题。
答案 2 :(得分:0)