Reputation: 531
I am practicing linked lists, and this is a code that is supplied to us by our lecturer, from a book by Pearson.
struct listNode {
char data;
struct listNode *nextPtr;
};
typedef struct listNode ListNode;
typedef ListNode *ListNodePtr;
...
char delete( ListNodePtr *sPtr, char value )
{
ListNodePtr previousPtr;
ListNodePtr currentPtr;
ListNodePtr tempPtr;
/* delete first node */
if ( value == ( *sPtr )->data ) {
tempPtr = *sPtr;
*sPtr = ( *sPtr )->nextPtr;
free ( tempPtr );
return value;
}
else{
previousPtr = *sPtr;
currentPtr = ( *sPtr )->nextPtr;
/* loop to find correct location in the list */
while ( currentPtr != NULL && currentPtr->data != value ) {
previousPtr = currentPtr;
currentPtr = currentPtr->nextPtr;
}
/* delete node at currentPtr */
if ( currentPtr != NULL ) {
tempPtr = currentPtr;
previousPtr->nextPtr = currentPtr->nextPtr;
free ( tempPtr );
return value;
}
}
return '\0';
}
I don't get why I'd need to use a "tempPtr". Could not I just do:
/* delete first node */
if ( value == ( *sPtr )->data ) {
*sPtr = ( *sPtr )->nextPtr;
free ( *sPtr );
return value;
}
and
if ( currentPtr != NULL ) {
previousPtr->nextPtr = currentPtr->nextPtr;
free ( currentPtr );
return value;
}
( What being passed to the delete
function is a LinkedListPtr
object defined in main
and is passed by reference. It's responsible to hold address of first element in the list. )
Upvotes: 0
Views: 122
Reputation: 44250
Simplified version:
struct listNode {
struct listNode *next;
char data;
};
char delete(struct listNode **pp, char value )
{
struct listNode *this;
while ((this = *pp)) {
if (this->data != value) { pp= &this->next; continue; }
*pp = this->next; // this is why you need a temp pointer
free(this); // ::because you want to free() it
return value; // nonsense return
}
return '\0'; // nonsense return
}
And a small driver to test the function:
#include <stdio.h>
#include <stdlib.h>
struct listNode {
struct listNode *next;
char data;
};
struct listNode *root = NULL;
void push(char val)
{
struct listNode *new;
new = malloc (sizeof *new);
new->data = val;
new->next = root;
root = new;
}
void print(struct listNode *p)
{
for (; p; p = p->next) {
printf(" %c", p->data);
}
printf("\n");
}
int main(void)
{
push('o');
push('l');
push('l');
push('e');
push('H');
print(root);
delete( &root, 'o');
print(root);
delete( &root, 'H'); // <<-- test if we can delete the **first** node of the chain
print(root);
return 0;
}
Upvotes: 2
Reputation: 141483
Could not I just do:
if ( value == ( *sPtr )->data ) { *sPtr = ( *sPtr )->nextPtr; # this line changes *sPtr value free ( *sPtr ); # frees `(*sPtr)->nextPtr`, not the old `*sPtr` return value; }
No, that's not equivalent. In your code you are freeing (*sPtr)->nextPtr
, not *sPtr
. You want to free the value of *sPtr
and change it to the value of the next pointer. So you have to have a temporary value - either for the pointer or for the new value. Alternatively to the original code, you could save nextPtr
and free the current pointer and then assign it to next:
if ( value == ( *sPtr )->data ) {
tempPtr = (*sPtr)->nextPtr;
free(*sPtr);
*sPtr = tempPtr;
return value;
}
and
if ( currentPtr != NULL ) { previousPtr->nextPtr = currentPtr->nextPtr; free ( currentPtr ); return value; }
Sure, that code is equivalent.
Upvotes: 2