Created
August 21, 2018 02:46
-
-
Save parkj90/df5fb427c9af1cb27ad71b8bcf051fe3 to your computer and use it in GitHub Desktop.
doubly linked list
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
//list.c | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include "list.h" | |
static void print(int value); | |
list_t *list_new(node_t *node) { | |
list_t *list = malloc(sizeof(list_t)); | |
if (!list) { | |
return NULL; | |
} | |
list->head = node; | |
list->tail = node; | |
list_update(list); | |
return list; | |
} | |
node_t *list_insert(node_t *node, bool dir, int value) { | |
node_t *new_node = malloc(sizeof(node_t)); | |
if (!new_node) { | |
return NULL; | |
} | |
new_node->data = value; | |
if (!node) { | |
new_node->next = NULL; | |
new_node->prev = NULL; | |
} else { | |
if (dir) { | |
new_node->next = node->next; | |
new_node->prev = node; | |
node->next = new_node; | |
} else { | |
new_node->next = node; | |
new_node->prev = node->prev; | |
node->prev = new_node; | |
} | |
} | |
return new_node; | |
} | |
node_t *list_append(list_t *list, bool dir, int value) { | |
if (!list) { | |
return NULL; | |
} | |
list_update(list); | |
node_t *new_node = malloc(sizeof(node_t)); | |
if (!new_node) { | |
return NULL; | |
} | |
if (!list->head || !list->tail) { | |
if (list->head != list->tail) { | |
free(new_node); | |
return NULL; | |
} | |
list->head = new_node; | |
list->tail = new_node; | |
} | |
if (dir) { | |
new_node->next = NULL; | |
new_node->prev = list->tail; | |
if (list->tail) { | |
list->tail->next = new_node; | |
list->tail = new_node; | |
} | |
} else { | |
new_node->next = list->head; | |
new_node->prev = NULL; | |
if (list->head) { | |
list->head->prev = new_node; | |
list->head = new_node; | |
} | |
} | |
new_node->data = value; | |
return new_node; | |
} | |
// function args: bool f(int value, int x); | |
node_t *list_search(list_t *list, bool dir, int value, bool (*f)(int, int)) { | |
if (!list || !list->head || !list->tail) { | |
return NULL; | |
} | |
list_update(list); | |
node_t *node; | |
if (dir) { | |
node = list->head; | |
while (!f(value, node->data)) { | |
if (!node->next) { | |
return NULL; | |
} | |
node = node->next; | |
} | |
} else { | |
node = list->tail; | |
while (!f(value, node->data)) { | |
if (!node->prev) { | |
return NULL; | |
} | |
node = node->prev; | |
} | |
} | |
return node; | |
} | |
// function args: void f(int value); | |
void list_traverse(list_t *list, bool dir, void (*f)(int)) { | |
if (!list || !list->head || !list->tail) { | |
return; | |
} | |
list_update(list); | |
node_t *node; | |
if (dir) { | |
node = list->head; | |
while (node) { | |
f(node->data); | |
node = node->next; | |
} | |
} else { | |
node = list->tail; | |
while (node) { | |
f(node->data); | |
node = node->prev; | |
} | |
} | |
} | |
unsigned int list_length(list_t *list) { | |
if (!list) { | |
return 0; | |
} | |
list_update(list); | |
unsigned int i = 0; | |
node_t *node = list->head; | |
while (node) { | |
node = node->next; | |
i++; | |
} | |
return i; | |
} | |
bool list_delete(list_t *list, node_t *node) { | |
if (!list || !node) { | |
return false; | |
} | |
list_update(list); | |
if (node->next) { | |
node->next->prev = node->prev; | |
} else { | |
list->tail = node->prev; | |
} | |
if (node->prev) { | |
node->prev->next = node->next; | |
} else { | |
list->head = node->next; | |
} | |
free(node); | |
return true; | |
} | |
bool list_get(node_t *node, int *value) { | |
if (!node) { | |
return false; | |
} | |
*value = node->data; | |
return true; | |
} | |
bool list_set(node_t *node, int value) { | |
if (!node) { | |
return false; | |
} | |
node->data = value; | |
return true; | |
} | |
bool list_update(list_t *list) { | |
if (!list) { | |
return false; | |
} | |
while(list->head->prev) { | |
list->head = list->head->prev; | |
} | |
while(list->tail->next) { | |
list->tail = list->tail->next; | |
} | |
return true; | |
} | |
void list_free(list_t *list) { | |
if (!list) { | |
return; | |
} | |
list_update(list); | |
node_t *node = list->head; | |
node_t *temp; | |
while (node) { | |
temp = node->next; | |
free(node); | |
node = temp; | |
} | |
free(list); | |
} | |
void list_dump(list_t *list, bool dir) { | |
list_update(list); | |
list_traverse(list, dir, print); | |
printf("\n"); | |
} | |
static void print(int value) { | |
printf("%d ", value); | |
} | |
/* for methods with direction (dir) arg | |
false - prev | |
true - next | |
*/ | |
/* methods returning bool should return: | |
false - if NULL pointer was given as arg | |
true - if function was succesfully called | |
*/ |
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
//list.h | |
#include <stdbool.h> | |
typedef struct list { | |
struct node *head; | |
struct node *tail; | |
} list_t; | |
typedef struct node { | |
struct node *next; | |
struct node *prev; | |
int data; | |
} node_t; | |
// for all dir(direction) args, true == next, false == prev | |
list_t *list_new(node_t *node); | |
node_t *list_insert(node_t *node, bool dir, int value); | |
node_t *list_append(list_t *list, bool dir, int value); | |
// function args: bool f(int value, int x); | |
node_t *list_search(list_t *list, bool dir, int value, bool (*f)(int, int)); | |
// function args: void f(int value); | |
void list_traverse(list_t *list, bool dir, void (*f)(int)); | |
unsigned int list_length(list_t *list); | |
bool list_delete(list_t *list, node_t *node); | |
bool list_get(node_t *node, int *value); | |
bool list_set(node_t *node, int value); | |
bool list_update(list_t *list); | |
void list_free(list_t *list); | |
void list_dump(list_t *list, bool dir); | |
/* methods returning bool should return: | |
false - if NULL pointer was given as arg | |
true - if function was succesfully called | |
*/ |
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
#include <stdio.h> | |
#include <assert.h> | |
#include "list.h" | |
bool test_function(int value, int x); | |
void print_double(int value); | |
void list_assert(list_t *list, int values[], unsigned int length); | |
int main(void) { | |
int value; | |
//Test insert | |
node_t *temp = list_insert(NULL, true, 32); | |
list_t *DLlist = list_new(temp); | |
if (!DLlist) { | |
printf("failed to allocated list\n"); | |
return -1; | |
} | |
temp = list_insert(temp, false, 22); | |
if (!list_update(DLlist)) { | |
printf("error updating list\n"); | |
} | |
list_insert(DLlist->head->next, true, 42); | |
list_dump(DLlist, true); | |
assert(list_length(DLlist) == 3); | |
list_assert(DLlist, (int[]){22, 32, 42}, 3); | |
//Test append | |
list_append(DLlist, true, 52); | |
list_append(DLlist, false, 12); | |
assert(list_length(DLlist) == 5); | |
list_dump(DLlist, true); | |
list_assert(DLlist, (int[]){12, 22, 32, 42, 52}, 5); | |
//Test search | |
temp = list_search(DLlist, true, 22, test_function); | |
assert(temp->data == 22); | |
temp = list_search(DLlist, false, 32, test_function); | |
assert(temp->data == 32); | |
temp = list_search(DLlist, false, 52, test_function); | |
assert(temp->data == 52); | |
assert(list_search(DLlist, true, 12, test_function)->data == 12); | |
//Test traverse | |
list_traverse(DLlist, true, print_double); | |
printf("\n"); | |
list_traverse(DLlist, false, print_double); | |
printf("\n"); | |
//Test delete | |
list_delete(DLlist, list_search(DLlist, true, 42, test_function)); | |
assert(list_length(DLlist) == 4); | |
list_delete(DLlist, DLlist->head); | |
assert(list_length(DLlist) == 3); | |
list_assert(DLlist, (int[]){22, 32, 52}, 3); | |
//Test get and set | |
list_get(DLlist->head, &value); | |
assert(value == 22); | |
list_set(DLlist->head, 100); | |
assert(DLlist->head->data == 100); | |
temp = DLlist->head->next; | |
list_get(temp, &value); | |
assert(value == 32); | |
list_set(temp, 101); | |
list_assert(DLlist, (int[]){100, 101, 52}, 3); | |
list_free(DLlist); | |
return 0; | |
} | |
bool test_function(int value, int x) { | |
if (value == x) { | |
return true; | |
} | |
return false; | |
} | |
void print_double(int value) { | |
printf("%d ", value * 2); | |
} | |
void list_assert(list_t *list, int values[], unsigned int length) { | |
if (!list) { | |
printf("assert error: list is a NULL pointer\n"); | |
return; | |
} | |
node_t *node = list->head; | |
for (unsigned int i = 0; i < length; i++) { | |
assert(node->data == values[i]); | |
node = node->next; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment