From: David Kastrup <dak@gnu.org>
To: git@vger.kernel.org
Subject: pointer to pointer (was: gitk problems: can't unset "idinlist(...)")
Date: Sat, 21 Jul 2007 11:32:50 +0200 [thread overview]
Message-ID: <85k5su9k59.fsf_-_@lola.goethe.zz> (raw)
In-Reply-To: alpine.LFD.0.999.0707202335570.27249@woody.linux-foundation.org
[-- Attachment #1: Type: text/plain, Size: 1445 bytes --]
Linus Torvalds <torvalds@linux-foundation.org> writes:
> Anyway, just because this is actually something I've noticed a lot
> of people do wrong, I actually do tend to think that when you
> traverse a singly-linked list and remove entries, you should *never*
> traverse the list itself, you should only ever traverse the "pointer
> to the pointer".
When I have doubly-linked lists where there is only forward traversal
(the backlink being for convenient deletions without context), I make
the backlink a pointer to pointer. This also means that one can
remove at the front of the list without needing to know the head
separately.
Anyway, here is some really, really ancient code of mine (file date is
of 1990 but it's older than that) which sorts linked lists stably
without extra storage and makes heavy use of pointer to pointer
traversal in both code and interface. There is also a strictly
non-recursive variant with the same data flow (except for never making
a redundant assignment) and just one instead of two functions which
consistently beats good qsort implementations, but this old version is
quite more fun to read.
Basically, if head is the pointer to a sorted list of at least n
elements, mergesort(&head, n) will sort the first n elements and
return a pointer to that link which contains the tail of the list. So
if you did not already 0-terminate your list, *mergesort(&head,n)=0;
will both sort and terminate your list.
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: Stable Mergesort on linked lists --]
[-- Type: text/x-csrc, Size: 1007 bytes --]
#include "mergesrt.h"
int (*mergecompare)(void *p1, void *p2);
int mergelink;
#define getlink(adr) (*(void**)((char*)(adr)+mergelink))
static void **merge(void **head1, void **tail1, void **tail2, unsigned n1, unsigned n2)
{
register void *p1 = *head1, *p2 = *tail1;
for(;;) {
if ((*mergecompare)(p1, p2) <= 0) {
p1 = *(head1 = &getlink(*head1 = p1));
if (--n1 == 0)
return *head1 = p2, tail2;
} else {
p2 = *(head1 = &getlink(*head1 = p2));
if (--n2 == 0)
return *tail1 = p2, *head1 = p1, tail1;
}
}
}
void **mergesort(void **head, unsigned n)
{
switch (n) {
case 0:
return head;
case 1:
return &getlink(*head);
case 2:
{
register void *p1, *p2;
p2 = getlink(p1 = *head);
if ((*mergecompare)(p1, p2) <= 0)
return &getlink(p2);
getlink(p1) = getlink(*head=p2);
return &getlink(getlink(p2) = p1);
}
default:
{
unsigned m;
void **h2;
n -= m = n / 2;
h2 = mergesort(head, n);
return merge(head,h2,mergesort(h2,m),n,m);
}
}
}
[-- Attachment #3: Type: text/plain, Size: 52 bytes --]
--
David Kastrup, Kriemhildstr. 15, 44793 Bochum
next prev parent reply other threads:[~2007-07-21 9:33 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-07-20 23:05 gitk problems: can't unset "idinlist(...)" Linus Torvalds
2007-07-21 5:09 ` Jeff King
2007-07-21 5:53 ` Linus Torvalds
2007-07-21 5:56 ` Junio C Hamano
2007-07-21 5:59 ` Jeff King
2007-07-21 6:06 ` Jeff King
2007-07-21 6:11 ` Linus Torvalds
2007-07-21 6:18 ` Jeff King
2007-07-21 6:24 ` Jeff King
2007-07-21 6:47 ` Linus Torvalds
2007-07-21 6:54 ` Jeff King
2007-07-21 9:32 ` David Kastrup [this message]
2007-07-21 9:44 ` pointer to pointer David Kastrup
2007-07-21 6:34 ` gitk problems: can't unset "idinlist(...)" Linus Torvalds
2007-07-21 11:42 ` Paul Mackerras
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=85k5su9k59.fsf_-_@lola.goethe.zz \
--to=dak@gnu.org \
--cc=git@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox