Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Finish doubly linked lists in Mastering Algos w C
- Loading branch information
Showing
2 changed files
with
186 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
|