E
Eric Sosman
Eric Sosman said:[... ghastly double-spacing fixed ...]
Op vrijdag 30 augustus 2013 14:51:50 UTC+2 schreef Eric Sosman:
On 8/30/2013 5:06 AM, Hans Vlems wrote:
[...]
Freeing the nodes last-to-first is probably not the best way,
especially if (as you suggest) the list may be long. First-to-last
is usually better, if you'll exercise just a tiny bit of care:
void freeList(struct node *head) {
while (head != NULL) {
struct node *next = head->link;
free(head);
head = next;
}
}
[...]
That's a classic tradeoff, right . The algorithm is either
head-to-tail, as you do and you need to declare temporary storage or
recursively, in which case the no additional declaration is needed at
the expense of a growing stack. In both cases memory is used.
Yes, memory is used -- but how much? For a list of N nodes,
last-to-first uses memory proportional to N to keep track of its
recursion[*], while first-to-last uses the same constant amount
of memory (two pointers' worth) no matter how long the list is.
I don't think you can say that without qualification, even in the
context of C. gcc can do tail-call optimisation and I've just checked
that I can write a recursive reverse-order freeing function that uses
constant extra space.
That's surprising. I reasoned: "If the head isn't freed until
after the tail, then the head-releaser does additional work after
the tail-releaser returns, so tail-call optimization doesn't apply."
But perhaps (or "likely") I've overlooked a clever rearrangement.
Would you be willing to share your code?
[*] A different last-to-first algorithm also uses constant
memory, but running time proportional to the *square* of N.
And yet another (very similar to the code you'd write to reverse a list
in-place) has linear running time and uses constant space. You've be
within your rights to call this a front-to back freeing of a reversed
list (slightly optimised), but it does free the nodes in reverse order.
Another way to look at it is that since a C linked-list can be reversed
in place in linear time with constant storage, there's no significant
difference between freeing the nodes in either order.
It seemed to me that the O.P.'s goal was not to free the nodes
in a specified order, but simply to free all the nodes. (He started
by asking whether `free(head)' would release the whole list.) From
his outline, I imagined something along the lines of
void freeList(struct node *head) {
if (head != NULL) {
freeList(head->link);
free(head);
}
}
.... and I wanted to point out a cheaper alternative.