#ifdef TEST_LLIST #include #endif /* TEST_LLIST */ #include typedef struct node { void* data; struct node* next; } node_t; node_t* new_node(void* data) { node_t* node = malloc(sizeof(node_t)); node->data = data; node->next = NULL; return node; } void* list_head(node_t* n) { return n->data; } node_t* list_tail(node_t* n) { return n->next; } /* appends node to end of ls, returns ls (obviously) linear in size of ls */ node_t* list_append(node_t* ls, node_t* node) { node_t* current = ls; if (ls == NULL) return node; while(current->next) current = current->next; current->next = node; return ls; } /* prepends node to beginning of ls, returns new ls (obviously) constant-time */ node_t* list_prepend(node_t* ls, node_t* node) { node->next = ls; return node; } /* frees all storage associated with a list (but NOT all data!) */ void list_cleanup(node_t* ls) { node_t* current = ls; node_t* tmp = current; while(current) { tmp = current->next; free(current); current = tmp; } } /* visits each data element on the list with specified function; for example, if your list were of malloc()ed character strings, you could call list_visit(ls, free); to free storage for each element before calling list_cleanup */ void list_visit(node_t* ls, void(*visitor)(void*)) { node_t* current = ls; while(current) { visitor(current->data); current = current->next; } } #ifdef TEST_LLIST void print_int(void* my_int) { int x = (int)my_int; printf("%d\n", x); } int main(int c, char *v) { node_t* ls = NULL; int i; for (i = 0; i < 10; i++) { ls = list_append(ls, new_node((void*)i)); } for (i = 20; i > 9; i--) { ls = list_prepend(ls, new_node((void*)i)); } list_visit(ls, print_int); list_cleanup(ls); exit(0); } #endif /* TEST_LLIST */