A doubly linked list implementation. All operations are O(1), including the ability to remove things from

within the list, assuming you already have an appropriate pointer to it.
This commit is contained in:
Sears Russell 2007-03-11 07:37:20 +00:00
parent 15e77da1d4
commit 8145e8db6f
2 changed files with 206 additions and 0 deletions

58
lladd/doubleLinkedList.h Normal file
View file

@ -0,0 +1,58 @@
#ifndef DOUBLE_LINKED_LIST_H
#define DOUBLE_LINKED_LIST_H
#define LL_ENTRY(foo) ll##foo
typedef void LL_ENTRY(value_t);
struct LL_ENTRY(node_t) {
LL_ENTRY(value_t) * v;
struct LL_ENTRY(node_t) * prev;
struct LL_ENTRY(node_t) * next;
};
struct LL_ENTRY(list) {
struct LL_ENTRY(node_t)* const head;
struct LL_ENTRY(node_t)* const tail;
};
struct LL_ENTRY(list)* LL_ENTRY(create)();
void LL_ENTRY(destroy)(struct LL_ENTRY(list) * l);
struct LL_ENTRY(node_t)* LL_ENTRY(push) (struct LL_ENTRY(list)* l,
LL_ENTRY(value_t) * v);
LL_ENTRY(value_t)* LL_ENTRY(pop) (struct LL_ENTRY(list)* l);
struct LL_ENTRY(node_t)* LL_ENTRY(unshift)(struct LL_ENTRY(list)* l,
LL_ENTRY(value_t) * v);
LL_ENTRY(value_t)* LL_ENTRY(shift) (struct LL_ENTRY(list)* l);
void LL_ENTRY(remove)(struct LL_ENTRY(list)* l,
struct LL_ENTRY(node_t)* n);
void LL_ENTRY(pushNode) (struct LL_ENTRY(list)* l,
struct LL_ENTRY(node_t) * v);
struct LL_ENTRY(node_t)* LL_ENTRY(popNode) (struct LL_ENTRY(list)* l);
void LL_ENTRY(unshiftNode)(struct LL_ENTRY(list)* l,
struct LL_ENTRY(node_t) * v);
struct LL_ENTRY(node_t)* LL_ENTRY(shiftNode) (struct LL_ENTRY(list)* l);
void LL_ENTRY(removeNoFree)(struct LL_ENTRY(list)* l,
struct LL_ENTRY(node_t)* n);
static inline LL_ENTRY(value_t*)LL_ENTRY(head)
(struct LL_ENTRY(list)* l) {
if(l->head->next != l->tail) {
return l->head->next->v;
} else {
return 0;
}
}
static inline LL_ENTRY(value_t*) LL_ENTRY(tail)
(struct LL_ENTRY(list)* l) {
if(l->tail->prev != l->head) {
return l->tail->prev->v;
} else {
return 0;
}
}
#endif

View file

@ -0,0 +1,148 @@
#include <config.h>
#include <stdlib.h>
#include <string.h>
#include <lladd/doubleLinkedList.h>
#include <assert.h>
typedef LL_ENTRY(value_t) value_t;
typedef struct LL_ENTRY(node_t) node_t;
typedef struct LL_ENTRY(list) list;
list * LL_ENTRY(create)() {
list* ret = malloc(sizeof(list));
// bypass const annotation on head, tail...
list tmp = {
malloc(sizeof(node_t)),
malloc(sizeof(node_t))
};
memcpy(ret, &tmp, sizeof(list));
ret->head->prev = 0;
ret->head->next = ret->tail;
ret->tail->prev = ret->head;
ret->tail->next = 0;
return ret;
}
void LL_ENTRY(destroy)(list* l) {
value_t * n;
while((n = LL_ENTRY(pop)(l))) {
// nop
}
free(l->head);
free(l->tail);
free(l);
}
node_t * LL_ENTRY(push)(list* l, value_t * v) {
node_t * n = malloc(sizeof(node_t));
n->v = v;
LL_ENTRY(pushNode)(l, n);
return n;
}
value_t* LL_ENTRY(pop) (list* l) {
node_t * n = LL_ENTRY(popNode)(l);
if(n) {
value_t * v = n->v;
free(n);
return v;
} else {
return 0;
}
}
node_t * LL_ENTRY(unshift)(list* l, value_t * v) {
node_t * n = malloc(sizeof(node_t));
n->v = v;
LL_ENTRY(unshiftNode)(l, n);
return n;
}
value_t * LL_ENTRY(shift) (list* l) {
node_t * n = LL_ENTRY(shiftNode)(l);
if(n) {
value_t * v = n->v;
free(n);
return v;
} else {
return 0;
}
}
void LL_ENTRY(pushNode)(list* l, node_t * n) {
// Need to update 3 nodes: n , tail, tail->prev
// n
n->prev = l->tail->prev;
n->next = l->tail;
// tail
l->tail->prev = n;
// tail->prev is now n->prev
n->prev->next = n;
}
node_t* LL_ENTRY(popNode) (list* l) {
node_t * n = l->tail->prev;
assert(n != l->tail);
if(n != l->head) {
assert(n->prev != 0);
assert(n->next == l->tail);
// n->prev
n->prev->next = n->next;
// tail
l->tail->prev = n->prev;
return n;
} else {
assert(n->prev == 0);
return 0;
}
}
void LL_ENTRY(unshiftNode)(list* l, node_t * n) {
// n
n->prev = l->head;
n->next = l->head->next;
// head
l->head->next = n;
// head->next is now n->next
n->next->prev = n;
}
node_t * LL_ENTRY(shiftNode) (list* l) {
node_t * n = l->head->next;
assert(n != l->head);
if(n != l->tail) {
assert(n->next != 0);
assert(n->prev == l->head);
// n->next
n->next->prev = n->prev;
// head
l->head->next = n->next;
return n;
} else {
assert(n->next == 0);
return 0;
}
}
void LL_ENTRY(remove)(list * l, node_t * n) {
LL_ENTRY(removeNoFree)(l,n);
free(n);
}
void LL_ENTRY(removeNoFree)(list * l, node_t * n) {
assert(n != l->head);
assert(n != l->tail);
assert(n->next != n);
assert(n->prev != n);
assert(n->next != n->prev);
n->prev->next = n->next;
n->next->prev = n->prev;
}