Skip to content

Instantly share code, notes, and snippets.

@parkj90
Created August 21, 2018 02:46
Show Gist options
  • Save parkj90/df5fb427c9af1cb27ad71b8bcf051fe3 to your computer and use it in GitHub Desktop.
Save parkj90/df5fb427c9af1cb27ad71b8bcf051fe3 to your computer and use it in GitHub Desktop.
doubly linked list
//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
*/
//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
*/
#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