删除的最低值以二进制搜索树 [英] Deleting the lowest value in a binary search tree
问题描述
我写了这个,不管怎样它的结束了删除我所有的左侧上树不仅是最左叶。
我找不到我的错误,有人可以帮忙吗?
结构节点* delMin(结构节点**根)
{
结构节点*电流= *根;
结构节点* b4Current; 而((电流 - > m_ls)== NULL){
b4Current =电流;
电流=电流 - > m_ls;
} 如果((电流 - > m_rs)== NULL){
b4Current-> m_ls = 0;
免费(电流);
}其他{
b4Current-> m_ls =电流 - > m_rs;
免费(电流);
} 返回*根;
}
让我们看看你的函数。
结构节点* delMin(结构节点**根)
您需要一个指向节点指针作为参数,返回新头。这是不必要的。返回头,如果不更新,否则它是唯一有用的。指针到节点的指针方式迎合了那个(恩,应该的,但事实并非如此),从而使返回值是免费的其它信息。
结构节点* b4Current;
在这里,你定义一个未初始化的指针。你应该把它初始化为 NULL
来idicate当前节点,头,没有一个家长。否则指针将是一个垃圾值,可能会导致不确定的行为。
,而((电流 - > m_ls)== NULL){
b4Current =电流;
电流=电流 - > m_ls;
}
在这里,你的情况是错误的:你想只要有一个指针向左走,但你做别的事情:你向左走,如果没有地方去!当头部有一个左孩子,电流
将留在头部。否则,这将是 NULL
,这将导致混乱,当您尝试取消对它的引用更高版本。
IF((电流 - > m_rs)== NULL){
b4Current-> m_ls = 0;
免费(电流); }其他{
b4Current-> m_ls =电流 - > m_rs;
免费(电流);
}
在的两个分支,如果
实际上是一样的,如果你仔细想想。这是一个有点像说:如果(X == 0)Y = 0;否则Y = X;
但你需要一个如果
在这里,即是当前的情况下区分
是头部或没有。在前一种情况下,你应该更新 *头
,后一种情况是你已经写了什么。
您也应该抓住,你不能从空的列表中删除一个节点的情况。
所以:
无效delMin(结构节点**根)
{
结构节点*电流= *根;
结构节点* b4Current = NULL; 如果(当前== NULL)返回NULL; 而(电流 - >!m_ls = NULL){
b4Current =电流;
电流=电流 - > m_ls;
} 如果(b4Current == NULL){
*根=电流 - > m_rs;
}其他{
b4Current-> m_ls =电流 - > m_rs;
} 免费(电流);
}
不过,因为你是一个指针传递给你的头节点反正,你可以简化功能:
无效delMin(结构节点**根)
{
如果(*根== NULL)回报; 而((*根) - GT;!m_ls = NULL){
根=及(*根) - GT; m_ls;
} 结构节点*旧= *根; (*根)=(*根) - GT; m_rs;
免费(旧);
}
您可能有一些难看的(*根)
在这儿,但你有很多的辅助变量的废除和如果
语句。的想法是,你通过用指针迭代到节点指针加一层间接。 *根
会对您的 b4Current
和(*根)的作用 - > m_ls
是电流
,但 *根
开始以一个合理的初始值,即根节点。
I wrote this and somehow it's ending up deleting all my left side on the tree not only the most left leaf.
I can't find my mistake, can someone help?
struct Node *delMin(struct Node **root)
{
struct Node *current = *root;
struct Node *b4Current;
while ((current->m_ls) == NULL) {
b4Current = current;
current = current->m_ls;
}
if ((current->m_rs) == NULL) {
b4Current->m_ls = 0;
free(current);
} else {
b4Current->m_ls = current->m_rs;
free(current);
}
return *root;
}
Let's look at your function.
struct Node *delMin(struct Node **root)
You take a pointer to node pointer as argument and return the new head. That is unnecessary. Returning the head is only useful if it isn't updated otherwise. Your pointer-to-node-pointer approach caters for that (well, it should, but it doesn't), so that the return value is free for other information.
struct Node *b4Current;
Here, you define an uninitialised pointer. You should initialise it to NULL
to idicate that the current node, the head, doesn't have a parent. Otherwise the pointer will be a garbage value that is likely to cause undefined behaviour.
while ((current->m_ls) == NULL) {
b4Current = current;
current = current->m_ls;
}
Here, your condition is wrong: You want to go left as long as there is a pointer, but you do something else: You go left if there isn't anywhere to go! When the head has a left child, current
will stay at the head. Otherwise, it will be NULL
, which will cause havoc when you try to dereference it later.
if ((current->m_rs) == NULL) {
b4Current->m_ls = 0;
free(current);
} else {
b4Current->m_ls = current->m_rs;
free(current);
}
The two branches of the if
are really the same, if you think about. It's a bit like saying: if (x == 0) y = 0; else y = x;
.
But you need an if
here, namely to distinguish between the case that current
is the head or not. In the former case, you should update *head
, the latter case is what you have already written.
You should also catch the case that you can't remove a node from an empty list.
So:
void delMin(struct Node **root)
{
struct Node *current = *root;
struct Node *b4Current = NULL;
if (current == NULL) return NULL;
while (current->m_ls != NULL) {
b4Current = current;
current = current->m_ls;
}
if (b4Current == NULL) {
*root = current->m_rs;
} else {
b4Current->m_ls = current->m_rs;
}
free(current);
}
But since you are passing a pointer to your head node anyways, you could simplify the function to:
void delMin(struct Node **root)
{
if (*root == NULL) return;
while ((*root)->m_ls != NULL) {
root = &(*root)->m_ls;
}
struct Node *old = *root;
(*root) = (*root)->m_rs;
free(old);
}
You may have some ugly (*root)
s here, but you do away with a lot of auxiliary variables and if
statements. The idea is that you add one level of indirection by iterating with a pointer to node pointer. *root
takes the role of your b4Current
and (*root)->m_ls
is your current
, except that *root
starts with a sensible initial value, namely the root node.
这篇关于删除的最低值以二进制搜索树的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!