Skip to content

Commit

Permalink
Finish doubly linked lists in Mastering Algos w C
Browse files Browse the repository at this point in the history
  • Loading branch information
davidxia committed Dec 15, 2012
1 parent 4a87dba commit 10156dd
Show file tree
Hide file tree
Showing 2 changed files with 186 additions and 0 deletions.
150 changes: 150 additions & 0 deletions algos_with_c/ch5/dlist.c
@@ -0,0 +1,150 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "dlist.h"


void dlist_init(DList *list, void (*destroy)(void *data)) {
list->size = 0;
list->destroy = destroy;
list->head = NULL;
list->tail = NULL;
return;
}


void dlist_destroy(DList *list) {
void *data;

while (dlist_size(list) > 0) {
if (dlist_remove(list, dlist_tail(list), (void **)&data) == 0
&& list->destroy != NULL) {
list->destroy(data);
}
}

/* Clear the structure as a precaution */
memset(list, 0, sizeof(DList));
return;
}


int dlist_ins_next(DList *list, DListElmt *element, const void *data) {
DListElmt *new_element;

/* Don't allow null element unless list is empty */
if (element == NULL && dlist_size(list) != 0)
return -1;

/* Allocate storage */
if ((new_element = (DListElmt *) malloc(sizeof(DListElmt))) == NULL)
return -1;

new_element->data = (void *)data;

if (dlist_size(list) == 0) {
list->head = new_element;
list->head->prev = NULL;
list->head->next = NULL;
list->tail = new_element;
} else {
new_element->prev = element;
new_element->next = element->next;

if (element->next == NULL)
list->tail = new_element;
else
element->next->prev = new_element;

element->next = new_element;

}

list->size++;
return 0;
}


int dlist_ins_prev(DList *list, DListElmt *element, const void *data) {
DListElmt *new_element;

/* Don't allow null element unless list is empty */
if (element == NULL && dlist_size(list) != 0)
return -1;

/* Allocate storage */
if ((new_element = (DListElmt *) malloc(sizeof(DListElmt))) == NULL)
return -1;

new_element->data = (void *)data;

if (dlist_size(list) == 0) {
list->head = new_element;
list->head->prev = NULL;
list->head->next = NULL;
list->tail = new_element;
} else {
new_element->prev = element->prev;
new_element->next = element;

if (element->prev == NULL)
list->head = new_element;
else
element->prev->next = new_element;

element->prev = new_element;

}

list->size++;
return 0;
}


int dlist_remove(DList *list, DListElmt *element, void **data) {
/* Don't allow NULL element or removal from empty list */
if (element == NULL || dlist_size(list) == 0)
return -1;

*data = element->data;
if (element == list->head) {
list->head = element->next;

if (list->head == NULL)
list->tail = NULL;
else
element->next->prev = NULL;
} else {
element->prev->next = element->next;
if (element->next == NULL)
list->tail = element->prev;
else
element->next->prev = element->prev;
}

free(element);
list->size--;
return 0;
}


int main() {
DList *list = (DList *) malloc(sizeof(DList));
DListElmt *element = (DListElmt *) malloc(sizeof(DListElmt));
dlist_init(list, free);

int *data1 = (int *) malloc(sizeof(int));
*data1 = 4;
int *data2 = (int *) malloc(sizeof(int));
*data2 = 9;
dlist_ins_next(list, NULL, data1);
dlist_ins_prev(list, dlist_head(list), data2);

for (element = dlist_head(list); element != NULL; element = dlist_next(element)) {
printf("element->data = %d\n", *((int *) element->data));
}

dlist_destroy(list);
return 0;
}

36 changes: 36 additions & 0 deletions algos_with_c/ch5/dlist.h
@@ -0,0 +1,36 @@
#ifndef DLIST_H
#define DLIST_H

#include <stdlib.h>


typedef struct DListElmt_ {
void *data;
struct DListElmt_ *prev;
struct DListElmt_ *next;
} DListElmt;

typedef struct DList_ {
int size;
int (*match)(const void *key1, const void *key2);
void (*destroy)(void *data);
DListElmt *head;
DListElmt *tail;
} DList;

/* Public interface */
void dlist_init(DList *list, void (*destroy)(void *data));
void dlist_destroy(DList *list);
int dlist_ins_next(DList *list, DListElmt *element, const void *data);
int dlist_ins_prev(DList *list, DListElmt *element, const void *data);
int dlist_remove(DList *list, DListElmt *element, void **data);
#define dlist_size(list) ((list)->size)
#define dlist_head(list) ((list)->head)
#define dlist_tail(list) ((list)->tail)
#define dlist_is_head(element) ((element)->prev == NULL ? 1 : 0)
#define dlist_is_tail(element) ((element)->next == NULL ? 1 : 0)
#define dlist_data(element) ((element)->data)
#define dlist_next(element) ((element)->next)
#define dlist_prev(element) ((element)->prev)
#endif

0 comments on commit 10156dd

Please sign in to comment.