Yeah, complex relationship networks grow a lot of hair. Going by some of your other comments, I'm sure you already know this, but this is one place where good variable naming is critical. "next? next what?"
The hairiness of dags and flow nodes in qfcc*, and the lack of importance in connection order is what made me really appreciate mixing arrays and sets. Multiple parents, multiple children, multiple peers (= dependencies). I found it easier to just have everything in an array, use a set for parents (if empty, a root node (yes, "a")), a set for all out-going edges (children and peers), and an array of pointers for the actual children (0-3) because child order
is important. BTW, this is now publicly available through git (see the qf site for details).
I've been using linked lists since I discovered pointers in Turbo Pascal 3, so I know just how frustrating they can be (and how fun
).
Take the following with a bag of salt. After writing it, I began to wonder how much I can recommend it, but I thought I'd leave it in as food for thought.
One suggestion I have if you use multiple doubly linked lists: put your next and previous pointers in a small link struct:
Code: Select all
struct messy {
struct {
struct messy *next;
struct messy *prev;
} peer_x;
struct {
struct messy *next;
struct messy *prev;
} peer_y;
....
};
I can't say that I've done this myself, but I did do something similar for the mess of sets connected to my flow nodes.
It would also be possible to have a separate link struct:
Code: Select all
struct link {
struct link *next;
struct link *prev;
void *data;
};
#define link_data(s,l,t) ((t *) (s)->l.data)
#define link_next(s,l,t) ((t*) (s)->l.next->data)
#define link_prev(s,l,t) ((t*) (s)->l.prev->data)
I'm not certain that wouldn't drive me up the wall, though.
I have to admit, I tend to avoid doubly linked lists when I have multiple links like this.