基本上我必须从链表中删除某个项目。 此代码有效:
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;
}
}
}
现在我尝试使用带有2指针的for来减少和压缩代码,但我无法弄清楚如何使其工作。 这是代码:
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);
}
}
}
答案 0 :(得分:1)
您可以使用以下附录
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 );
}
}
如果要删除成员item
等于client
的所有节点,那么确实可以使用for循环。
例如
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;
}
}
}
答案 1 :(得分:1)
有两个错误点:
答案 2 :(得分:0)
删除项目时,必须知道要更新的指针。这意味着您必须知道列表中的上一个节点。弗拉德的答案通过保留一个额外的previous
变量来做到这一点,你的第一个代码通过查看当前节点指向的指针来做到这一点。两者都必须将头部删除视为特例。
你的第二个代码试图简化代码,但是你会失去删除头部的特殊情况,并在删除后更新迭代器链接,你不应该这样做。 (您的原始代码正确地将更新放在else
子句中。)
一种摆脱头部删除特殊情况的方法是通过指向节点指针的指针通过iterationg引入一级间接。该指针保存" previous"的地址。指针 - 前一节点的列表头或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;
}
}
}
此代码会删除与client
匹配的所有项目;我认为这是理想的行为。 (附加的间接也适用于插入。)