[英]Deleting from a List in C
Basically I have to delete a certain item from a linked list. 基本上,我必须从链接列表中删除某个项目。 This code works:
此代码有效:
void delete_(Item client){
link s=head,r;
if(head->item==client){
r=head;
head=head->next;
free(r);
}
else{
while(s->next!=NULL){
if(s->next->item==client){
r=s->next;
s->next=s->next->next;
free(r);
}
else
s=s->next;
}
}
}
Now I tried to reduce and compact the code using a for with 2 pointer but I can't figure out how to make it works. 现在,我尝试使用带有2指针的for来减少和压缩代码,但是我不知道如何使其工作。 Here's the code:
这是代码:
void delete_(Item client){
link x,r,p;
for(x=head;x!=NULL;p=x,x=x->next){
if(x->item==client){
r=x;
p->next=x->next;
free(r);
}
}
}
You can use for example the following appeoach 您可以使用例如以下方法
void delete( Item client )
{
link current = head, previous = NULL;
while ( current && current->item != client )
{
previous = current;
current = current->next;
}
if ( current )
{
if ( !previous ) head = head->next;
else previous->next = current->next;
free( current );
}
}
If you want to delete all nodes that have member item
equal to client
then indeed you can use a for loop. 如果要删除成员
item
等于client
所有节点,则确实可以使用for循环。
For example 例如
void delete( Item client )
{
for( link current = head, previous = NULL; current != NULL; )
{
if ( current->item == client )
{
link tmp = current;
if ( previous != NULL )
{
previous->next = current->next;
current = current->next;
}
else
{
head = current->next;
current = head;
}
free( tmp );
}
else
{
previous = current;
current = current->next;
}
}
}
There are two wrong points: 有两个错误的观点:
When you delete an item, you must know which pointer to update. 删除项目时,必须知道要更新的指针。 That means you must know about the previous node in the list.
这意味着您必须了解列表中的上一个节点。 Vlad's answer does this by keeping an extra
previous
variable, your first code does that by looking at the pointer pointed to by the current node. Vlad的答案是通过保留一个额外的
previous
变量来实现的,您的第一个代码通过查看当前节点所指向的指针来做到这一点。 Both have to treat deletion from the head as special case. 两者都必须将头部删除视为特殊情况。
Your second code tries to simplify the code, but you lose the special case of deletion at the head and also update the iterator link after deletion, which you shouldn't. 您的第二个代码试图简化代码,但是您丢失了删除开头的特殊情况,并且在删除后也更新了迭代器链接,这是不应该的。 (Your original code correctly places the update in an
else
clause.) (您的原始代码正确地将更新放置在
else
子句中。)
A method to get rid of the special case of deletion at the head is to introduce one level of indirection by iterationg via a pointer to node pointer. 摆脱头部特殊删除的一种方法是通过指向节点指针的指针通过迭代引入一个间接级别。 That pointer holds the address of the "previous" pointer – the list head or the
next
pointer of the previous node. 该指针保存“上一个”指针的地址-列表头或上
next
节点的next
指针。 The rest is more or less like your original code, expect that the current node now is at *l
instead of at l->next
: 其余部分或多或少类似于您的原始代码,希望当前节点现在位于
*l
而不是l->next
:
void delete(Item client)
{
link *l = &head;
while (*l) {
if ((*l)->client == client) {
link r = *l;
*l = (*l)->next;
free(r);
} else {
l = &(*l)->next;
}
}
}
This code removes all items that match client
; 此代码删除所有与
client
匹配的项目; I reckon that is the desired behaviour. 我认为这是理想的行为。 (The additional indirection also works for insertion.)
(附加的间接方式也适用于插入。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.