Linked Lists 301
Node * p;
p = head;
Node * q;
q = p -> next;
p -> next = q -> next;
free (q);
symbol
value
address value
q202-
83001 326
p 201 83000
83000 60000
head 200 83000
60001 917
60000 NULL
Call Stack Heap Memory
(a)
(c)
head
(b)
326
p
q
FIGURE 18.10: Release the memory pointed to by q.
return head;
32
}33
If head’s value (head -> value)isthesameasval, the first node is deleted. This is
achieved by storing head -> next in p at line 14. In this case, the function returns p as the
new head of the list. It is possible that p is set to NULL. This occurs when the list has only
one node and its value is the same as val. After deleting this node, the list is empty.
If head’s value is different from val, then the node to be deleted, if it exists, is after
head somewhere. When we find this node, we must make the previous node point to the
next node. As we will see below, the List
delete function uses another pointer q for this
purpose, and its value is p -> next.
Lines 20 to 25 find the node whose value is val.Thewhile loop stops in one of two
conditions: either q is NULL or q -> value is val. To avoid a memory error, the function
must check the first condition before checking the second condition. If q is NULL,then
the second condition is not checked. When q is NULL, the first part of the logical AND
(&&) expression is false and the entire logical AND expression is false. The program does
check whether q -> value is the same as val. This is called short-circuit evaluation and
C programs often rely on it. Lines 23 and 24 move p and q to their next nodes. Since q is
initialized to p -> next, the code inside the entire block always keeps q as p -> next.
What does it means when q is NULL at line 26? It means that no node in the linked
list stores val, and therefore no node needs to be deleted. If q is not NULL, then a node
whose value is val has been located. The function changes p -> next to q -> next.This
bypasses the node q that is about to be deleted. In this method, q isthenodetobedeleted
and p is the node before q. It is necessary to keep p because it is not possible to go backward
from q to p. The purpose of keeping both p and q is that we cannot go back one node from
q without p. The function then releases the memory pointed to by q. The value stored in q
is
still a memory address but that address is no longer valid. Using q’s value after free(q)
will cause segmentation fault. It is also possible to implement List
delete with recursion.
Below is a sample implementation. Lines 19 to 31 above can be replaced by a single line as
shown below.
Node * List_delete2(Node * head, int val)
1