使用给定密钥删除BST中的节点的功能如下:
struct node* deleteNode(struct node* root, int key)
{
// base case
if (root == NULL) return root;
// If the key to be deleted is smaller than the root's key,
// then it lies in left subtree
if (key < root->key)
root->left = deleteNode(root->left, key);
// If the key to be deleted is greater than the root's key,
// then it lies in right subtree
else if (key > root->key)
root->right = deleteNode(root->right, key);
// if key is same as root's key, then This is the node
// to be deleted
else
{
// node with only one child or no child
if (root->left == NULL)
{
struct node *temp = root->right;
free(root);
return temp;
}
else if (root->right == NULL)
{
struct node *temp = root->left;
free(root);
return temp;
}
// node with two children: Get the inorder successor (smallest
// in the right subtree)
struct node* temp = minValueNode(root->right);
// Copy the inorder successor's content to this node
root->key = temp->key;
// Delete the inorder successor
root->right = deleteNode(root->right, temp->key);
}
return root;
}
考虑具有前序遍历的树为:50 30 20 40 70 60 80
我希望删除节点20.函数调用如下:
deleteNode(root=50, 20)
deleteNode(root=30, 20)
deleteNode(root=20, 20)
当它到达此调用(deleteNode(20,20))时,执行else部分。自root->left == NULL
起,剪切的代码执行为:
temp = root->right (which is NULL)
free (root)
return temp (returning NULL)
它会返回上一个电话root->left = deleteNode(20, 20) = NULL
。其他调用(即deleteNode(30, 20) and deleteNode(50, 20)
)会发生什么,并在执行结束时返回根。实际上返回了哪个根?
答案 0 :(得分:2)
回答&#34;实际返回了哪些根&#34; ......他们都是。问题是他们返回的地方是什么,最终价值是多少。
当您在代码中向前搜索时,您会看到执行递归函数调用的位置,并了解您创建了具有不同值的函数的新副本,并再次从顶部跟踪。你现在正在解开这个过程。
从您离开的地方开始,您return temp
的值为root->left = deletenode(20, 20)
的{{1}},如您所知。您现在可以从该点恢复执行。 else if
和else
条件不会被神奇地重新评估,您可以放到左侧节点设置为NULL的return root
。然后将此根返回到deletenode(30,20)
,然后用返回的值替换左侧或右侧部分。
此模式将继续,直到所有函数调用都已解决。名称root
可能令人困惑,但它是&#34; root&#34;在递归期间创建的每个子树的唯一形成原始树的分支。
使用您的值提供一些说明:
50 <- root for deletenode("node 50", x)
/ \
30 70 <- root for deletenode("node 50"-> left or right, x)
/ \ / \
20 40 60 80 <- root for deletenote("node 50"->left/right->left/right,x)
尝试追踪你:
追踪结束。
您返回的树现在看起来像:
50 <- root for deletenode("node 50", x)
/ \
30 70 <- root for deletenode("node 50"-> left or right, x)
/ \ / \
NULL 40 60 80 <- root for deletenote("node 50"->left/right->left/right,x)
答案 1 :(得分:1)
我认为理解递归函数的“技巧”是首先理解非递归函数,然后认识到递归函数完全相同。
想象一下,您对树的每个级别都有一个函数 - deleteNode_1
,deleteNode_2
,deleteNode_3
,依此类推。
您可以通过将树的根目录传递给deleteNode_1
来进行第一次通话。
如果要删除的节点位于其参数的子树中,deleteNode_1
将使用该子树调用deleteNode_2
,并将其参数的一个子树替换为结果。
对deleteNode_2
的调用可能会调用deleteNode_3
,依此类推,但deleteNode_1
不需要关心这一点,它只关心从{{获取合适的子树1}}。
它们看起来像这样:
deleteNode_2
并按照以下方式实施:
// Delete a node when 'current' is at level 1
struct node* deleteNode_1(struct node* current, int key);
// Delete a node when 'current' is at level 2
struct node* deleteNode_2(struct node* current, int key);
// Delete a node when 'current' is at level 3
struct node* deleteNode_3(struct node* current, int key);
// .. and so on, as many as you need.
如果您了解这些函数的工作原理,那么理解递归函数的步骤非常小。