Reputation: 15
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. 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);
}
}
}
Upvotes: 0
Views: 96
Reputation: 29126
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. 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.)
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. The rest is more or less like your original code, expect that the current node now is at *l
instead of at 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
; I reckon that is the desired behaviour. (The additional indirection also works for insertion.)
Upvotes: 0
Reputation: 310990
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.
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;
}
}
}
Upvotes: 1
Reputation: 583
There are two wrong points:
Upvotes: 1