无法从链表中删除最后一个元素
cannot remove the last element from linked list
我无法从链表中删除最后一个元素,问题是当我删除它时,我拥有的唯一节点是前一个节点(在最后一个节点之前)。这是我的代码:
node *remove_node(int d, node *lst){
node *prev;
node *temp = lst;
if(temp->data == d){
if(temp->next != NULL){
node *sec_temp = temp;
temp = temp->next;
free(sec_temp);
return temp;
}
else{
free(temp);
return NULL;
}
}
while(temp != NULL && temp->data != d){
prev = temp;
temp = temp->next;
}
if(temp == NULL){return lst;}
//Here is the problem
if(temp->next == NULL){
prev->next = NULL;
free(temp);
return prev;
}
//end
else {
prev->next = temp->next;
free(temp);
return prev;
}
}
int main(){
node *lst = NULL;
lst = new_node(1, lst);
lst = new_node(2, lst);
lst = new_node(3, lst);
lst = new_node(4, lst);
lst = remove_node(1, lst);
print(lst);// this will print the list, works perfect
return 0;
}
当我删除 1(这是列表中的最后一个元素)时,只会打印 2,在所有其他情况下一切正常(如果我删除 2 或 3 或 4 我没有任何问题。 ).
有什么想法可能会导致问题吗?
你把事情搞得比需要的复杂得多。有几种方法可以删除正向 linked、空终止 linked 列表中的节点。您可以使用两个指针(前一个指针和当前指针)来完成它,这似乎是您正在尝试的。在理解实际算法之前停止编码:
node *remove_node(int d, node *lst)
{
node *prev = NULL, *cur = lst;
while (cur && cur->data != d)
{
prev = cur;
cur = cur->next;
}
if (cur)
{
if (!prev) // head node was the match
lst = lst->next;
else
prev->next = cur->next;
free(cur);
}
return lst;
}
工作原理
最初我们有两个指针,prev
指向列表中的前一个节点到当前测试节点并且最初为 NULL,cur
,我们正在测试的当前节点,最初是列表头。
一次遍历列表一个节点,每次测试我们是否 (a) 尚未到达列表末尾 (cur != NULL
) 和 (b) 找到与我们的目标数据匹配的节点(cur->data == d
)。我们相应地打破循环。一旦循环中断,cur
要么指向要删除的节点,要么为 NULL,这意味着我们找不到匹配项。
prev
的值仅在 cur
为非 NULL 时才重要,这意味着我们找到了匹配项。如果我们找到一个匹配项并且 prev == NULL
我们 必须 在头节点上,否则 prev
指的是 next
指针需要 link 到 cur->next
指针来拼接列表并在删除之前删除我们的受害者。
仅此而已。我 强烈 建议您通过调试器手动执行删除操作,并查看指针沿途处理的内容。调试器不仅仅用于查找损坏的东西。它们是帮助更好地理解代码工作原理的绝佳工具(因为您实际上 "see" 它在工作)。
祝你好运。
问题是你 returns 指向被删除元素之前的元素的 prev
指针,但实际上列表的开头仍然是 lst
指针。接下来在 main
方法中,您在打印方法中使用返回的指针,因此您只打印最后一个元素。
我无法从链表中删除最后一个元素,问题是当我删除它时,我拥有的唯一节点是前一个节点(在最后一个节点之前)。这是我的代码:
node *remove_node(int d, node *lst){
node *prev;
node *temp = lst;
if(temp->data == d){
if(temp->next != NULL){
node *sec_temp = temp;
temp = temp->next;
free(sec_temp);
return temp;
}
else{
free(temp);
return NULL;
}
}
while(temp != NULL && temp->data != d){
prev = temp;
temp = temp->next;
}
if(temp == NULL){return lst;}
//Here is the problem
if(temp->next == NULL){
prev->next = NULL;
free(temp);
return prev;
}
//end
else {
prev->next = temp->next;
free(temp);
return prev;
}
}
int main(){
node *lst = NULL;
lst = new_node(1, lst);
lst = new_node(2, lst);
lst = new_node(3, lst);
lst = new_node(4, lst);
lst = remove_node(1, lst);
print(lst);// this will print the list, works perfect
return 0;
}
当我删除 1(这是列表中的最后一个元素)时,只会打印 2,在所有其他情况下一切正常(如果我删除 2 或 3 或 4 我没有任何问题。 ). 有什么想法可能会导致问题吗?
你把事情搞得比需要的复杂得多。有几种方法可以删除正向 linked、空终止 linked 列表中的节点。您可以使用两个指针(前一个指针和当前指针)来完成它,这似乎是您正在尝试的。在理解实际算法之前停止编码:
node *remove_node(int d, node *lst)
{
node *prev = NULL, *cur = lst;
while (cur && cur->data != d)
{
prev = cur;
cur = cur->next;
}
if (cur)
{
if (!prev) // head node was the match
lst = lst->next;
else
prev->next = cur->next;
free(cur);
}
return lst;
}
工作原理
最初我们有两个指针,prev
指向列表中的前一个节点到当前测试节点并且最初为 NULL,cur
,我们正在测试的当前节点,最初是列表头。
一次遍历列表一个节点,每次测试我们是否 (a) 尚未到达列表末尾 (cur != NULL
) 和 (b) 找到与我们的目标数据匹配的节点(cur->data == d
)。我们相应地打破循环。一旦循环中断,cur
要么指向要删除的节点,要么为 NULL,这意味着我们找不到匹配项。
prev
的值仅在 cur
为非 NULL 时才重要,这意味着我们找到了匹配项。如果我们找到一个匹配项并且 prev == NULL
我们 必须 在头节点上,否则 prev
指的是 next
指针需要 link 到 cur->next
指针来拼接列表并在删除之前删除我们的受害者。
仅此而已。我 强烈 建议您通过调试器手动执行删除操作,并查看指针沿途处理的内容。调试器不仅仅用于查找损坏的东西。它们是帮助更好地理解代码工作原理的绝佳工具(因为您实际上 "see" 它在工作)。
祝你好运。
问题是你 returns 指向被删除元素之前的元素的 prev
指针,但实际上列表的开头仍然是 lst
指针。接下来在 main
方法中,您在打印方法中使用返回的指针,因此您只打印最后一个元素。