Ten years ago, I was shown a technique for traversing a linked list: instead of using a single pointer, you used a double pointer (pointer-to-pointer).
The technique yielded smaller, more elegant code by eliminating the need to check for certain boundary/edge cases.
Does anyone know what this technique actually is?
I think you mean double pointer as in "pointer to a pointer" which is very efficient for inserting at the end of a singly linked list or a tree structure. The idea is that you don't need a special case or a "trailing pointer" to follow your traversal pointer once you find the end (a NULL pointer). Since you can just dereference your pointer to a pointer (it points to the last node's next pointer!) to insert. Something like this:
T **p = &list_start;
while (*p) {
p = &(*p)->next;
}
*p = new T;
instead of something like this:
T *p = list_start;
if (p == NULL) {
list_start = new T;
} else {
while (p->next) {
p = p->next;
}
p->next = new T;
}
NOTE: It is also useful for making efficient removal code for a singly linked list. At any point doing *p = (*p)->next
will remove the node you are "looking at" (of course you still need to clean up the node's storage).
By "double-pointer", I think you mean "pointer-to-pointer". This is useful because it allows you to eliminate special cases for either the head or tail pointers. For example, given this list:
struct node {
struct node *next;
int key;
/* ... */
};
struct node *head;
If you want to search for a node and remove it from the list, the single-pointer method would look like:
if (head->key == search_key)
{
removed = head;
head = head->next;
}
else
{
struct node *cur;
for (cur = head; cur->next != NULL; cur = cur->next)
{
if (cur->next->key == search_key)
{
removed = cur->next;
cur->next = cur->next->next;
break;
}
}
}
Whereas the pointer-to-pointer method is much simpler:
struct node **cur;
for (cur = &head; *cur != NULL; cur = &(*cur)->next)
{
if ((*cur)->key == search_key)
{
removed = *cur;
*cur = (*cur)->next;
break;
}
}
I think you mean doubly-linked lists where a node is something like:
struct Node {
(..) data // The data being stored in the node, it can be of any data type
Node *next; // A pointer to the next node; null for last node
Node *prev; // A pointer to the previous node; null for first node
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With