Here's a generic approach:
Code:
void repoint_neighbors(Node * self, Node * p, Node * n){
if(self->next) self->next->prev = p;
if(self->prev) self->prev->next = n;
}
void repoint_self(Node * self, Node * p, Node * n){
self->next = n;
self->prev = p;
}
Node * insert_node(Node * self, Node * p, Node * n){
repoint_self(self, p, n);
repoint_neighbors(self, self, self);
return self;
}
Node * extract_node(Node * self){
repoint_neighbors(self, self->prev, self->next);
repoint_self(self, 0, 0);
return self;
}
Node * insert_new_node(Node * p, Node * n){
Node * self = malloc(sizeof(Node));
if(self != NULL) insert_node(self, p, n);
return self;
}
void delete_node(Node * self){
free( extract_node(self) );
}
Thus, there is really not much code behind linked lists. It's merely an issue of making sure you do things in the correct order, nothing else. You should always seek to create generic solutions too, easier to debug and alter, and arguably more readable.