所以我正在开发BST,构建删除工具。
我的代码序列似乎工作正常 - 保存不更新父或根,并将发送它的指针设置为已删除的节点的地址为NULL。
我正在向Erase和RemoveNode函数中的指针传递指针,以便直接影响实际导致递归调用的左,右或根数据成员。在遍历代码时,它在remove函数中将* N设置为NULL,但这不会反映在调用对象的数据中。我使用指针指针方法不正确吗?如果是这样,有没有办法可以递归删除,并且如果链接被破坏,能够修改先前的节点?
节点结构:
struct tNode
{
tNode(int n)
{
data = n;
left = NULL;
right = NULL;
}
//Works, cleans all linked objects.
//Must remember to null links when removing wanted nodes
~tNode(void)
{
//cout << "Deleting " << data << endl;
delete left;
delete right;
}
// Data members
int data;
tNode* left;
tNode* right;
};
橡皮擦功能来递归树:
void BinSearchTree::Erase(int n, tNode** N)
{
tNode* node = *N;
if (root)
{
if (node->data > n) // post order, to avoid moving many times over
{
if (node->left)
{
Erase(n, &node->left);
}
}
else
{
if (node->right)
{
Erase(n, &node->right);
}
}
if (node->data == n)
{
RemoveNode(&node);
}
}
}
用于处理实际删除的RemoveNode函数:
void BinSearchTree::RemoveNode(tNode** N)
{
tNode* node = *N;
if (!node->left && !node->right) // is leaf
{
delete node; // remove node
size--;
*N = NULL; // null pointer for above node/structure
}
else if (!node->left) // right child
{
tNode* temp = node->right; // to strip out copied node when finished
node->data = node->right->data; // copy right node into current node
node->right = node->right->right;
node->left = node->right->left;
temp->right = NULL; // NULL because node destructor is recursive
temp->left = NULL; // ^^
delete temp;
size--;
}
else if (!node->right) // left child
{
tNode* temp = node->left; // to strip out copied node when finished
node->data = node->left->data; // copy left node into current node
node->right = node->left->right;
node->left = node->left->left;
temp->right = NULL; // NULL because node destructor is recursive
temp->left = NULL; // ^^
delete temp;
size--;
}
else // 2 children
{
tNode* temp = node->right; // find ideal child -> left-most right child
tNode* parent = NULL; // keep track of owner of ideal child
while (temp->left)
{
parent = temp;
temp = temp->left;
}
node->data = temp->data; // copy ideal child to root
if (parent)
{
parent->left = temp->right; // case that left-most child has right child of it's own
}
RemoveNode(&temp);
size--;
}
}
答案 0 :(得分:1)
我想我明白了。当您从RemoveNode()
致电Erase()
时,您会传递值&node
。改为通过N
。
以下是发生的事情:行tNode* node = *N;
在堆栈上创建一个局部变量。 *N
的副本。虽然该变量与* N(起初)具有相同的值,但它存储在内存中的不同位置:node
位于堆栈中,*N
位于堆中的某个位置。
因此,自从&node
传递给RemoveNode()
后,node
就会发生变化。不是*N
- 它在其他地方。但如果你传入,你就会改变你想要的东西。
希望有所帮助!
PS:如果不清楚,请告诉我!写关于双指针可能比使用它们更难......答案 1 :(得分:0)
省去使用双指针的麻烦,只需使用对指针的引用。它们具有与普通指针相同的语义,但是分配它们实际上会改变传递的指针。
void BinSearchTree::Erase(int item, tNode*& node);
此外,使用富有表现力的名称并保存循环的单字母变量名称。