Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

linked list cleanup #26

Merged
merged 7 commits into from
Jan 4, 2020
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
clean-up linked lists code for maintainability and readability; fix e…
…dge case
barrust committed Jan 4, 2020
commit 62931dd5615c74b9089ac410708a312fb8169371
152 changes: 56 additions & 96 deletions src/dllist.c
Original file line number Diff line number Diff line change
@@ -4,7 +4,6 @@
#include "dllist.h"



typedef struct __doubly_linked_list {
dll_node* head;
dll_node* tail;
@@ -17,7 +16,6 @@ dllist_t dll_init() {
l->head = NULL;
l->tail = NULL;
l->elms = 0;

return l;
}

@@ -51,36 +49,11 @@ dll_node* dll_last_node(dllist_t l) {
}

int dll_append(dllist_t l, void* data) {
dll_node* n = calloc(1, sizeof(dll_node));
if (n == NULL)
return DLL_FAILURE;

n->data = data;
n->next = NULL;
n->prev = NULL;

if (l->elms == 0) {
l->tail = n;
l->head = n;
++(l->elms);
return DLL_SUCCESS;
}

l->tail->next = n;
n->prev = l->tail;
l->tail = n;
++(l->elms);

return DLL_SUCCESS;
return dll_insert(l, data, -1);
}

int dll_insert(dllist_t l, void * data, int idx) {
/* first, ensure we handle appending to the end, no matter the number of
elements already present */
if (idx == -1)
return dll_append(l, data);

if (idx < 0 && idx <= (-1 * (int)l->elms))
if (idx != -1 && idx < 0 && idx <= (-1 * (int)l->elms))
return DLL_FAILURE;

if (idx < 0)
@@ -95,38 +68,38 @@ int dll_insert(dllist_t l, void * data, int idx) {
n->next = NULL;
n->prev = NULL;

if (idx == 0) {
if (l->elms == 0) { /* first node to be added edge case */
l->head = n;
l->tail = n;
} else if (idx == 0) { /* first node */
n->next = (l->head);
n->next->prev = n;
l->head = n;
++(l->elms);
return DLL_SUCCESS;
} else if (idx >= (int)l->elms) {
} else if (idx >= (int)l->elms) { /* last node */
l->tail->next = n;
n->prev = l->tail; /* we want the tail to point to the end */
l->tail = n;
++(l->elms);
return DLL_SUCCESS;
}

int i;
dll_node* t;
if (idx <= (int)l->elms / 2) {
t = dll_first_node(l);
for (i = 1; i < idx; i++)
t = t->next;
} else {
/* start from the tail and go backwards! */
int stop = l->elms - idx;
t = dll_last_node(l);
for (i = 0; i < stop; i++)
t = t->prev;
} else { /* mid node; determine which direction would be fastest to get to it */
int i;
dll_node* t;
if (idx <= (int)l->elms / 2) {
t = dll_first_node(l);
for (i = 1; i < idx; i++)
t = t->next;
} else {
/* start from the tail and go backwards! */
int stop = l->elms - idx;
t = dll_last_node(l);
for (i = 0; i < stop; i++)
t = t->prev;
}

n->next = t->next;
t->next = n;
n->next->prev = n;
n->prev = t;
}

n->next = t->next;
t->next = n;
n->next->prev = n;
n->prev = t;
++(l->elms);
return DLL_SUCCESS;
}
@@ -144,52 +117,39 @@ void* dll_remove(dllist_t l, int idx) {
if (idx < 0)
idx = l->elms + idx;

void* ret;
dll_node* n;
if (l->elms == 1) { /* this is the oddest edge case */
n = l->head;
ret = n->data;
l->head = NULL;
l->tail = NULL;
--l->elms;
free(n);
return ret;
} else if (idx == 0) { /* handle edge cases */
n = l->head;
ret = n->data;
void* data;
dll_node* ret;
if (l->elms == 1) { /* remove the final node */
ret = l->head;
l->head = l->tail = NULL;
} else if (idx == 0) { /* remove the first node */
ret = l->head;
l->head = l->head->next;
l->head->prev = NULL;
--l->elms;
free(n);
return ret;
} else if (idx >= (int)(l->elms - 1)) {
n = l->tail;
ret = n->data;
l->tail = n->prev;
n->prev->next = NULL;
--l->elms;
free(n);
return ret;
}

int i;
if (idx <= (int)l->elms / 2) {
n = dll_first_node(l);
for (i = 1; i < idx; i++)
n = n->next;
ret = l->tail;
l->tail = ret->prev;
ret->prev->next = NULL;
} else {
/* start from the tail and go backwards! */
int stop = l->elms - idx;
n = dll_last_node(l);
for (i = 0; i < stop; i++)
n = n->prev;
int i;
if (idx <= (int)l->elms / 2) {
ret = dll_first_node(l);
for (i = 1; i < idx; i++)
ret = ret->next;
} else {
/* start from the tail and go backwards! */
int stop = l->elms - idx;
ret = dll_last_node(l);
for (i = 0; i < stop; i++)
ret = ret->prev;
}

/* move the nodes before and after's pointers around */
ret->prev->next = ret->next;
ret->next->prev = ret->prev;
}

/* mode the nodes before and after's pointers around */
n->prev->next = n->next;
n->next->prev = n->prev;
ret = n->data;
--l->elms;
free(n);
return ret;
data = ret->data;
--(l->elms);
free(ret);
return data;
}
2 changes: 1 addition & 1 deletion src/dllist.h
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@
*** Author: Tyler Barrus
*** email: barrust@gmail.com
***
*** Version: 0.1.0
*** Version: 0.1.1
*** Purpose: Generic doubly linked list implementation
***
*** License: MIT 2019
50 changes: 23 additions & 27 deletions src/llist.c
Original file line number Diff line number Diff line change
@@ -56,47 +56,43 @@ int ll_insert(llist_t l, void* data, size_t idx) {
if (l->elms == 0 || idx == 0) {
t->next = l->head;
l->head = t;
++l->elms;
return LL_SUCCESS;
} else {
ll_node* n = l->head;
size_t i = 1;
while (n->next != NULL) {
if (i++ == idx)
break;
n = n->next;
}
t->next = n->next;
n->next = t;
}

ll_node* n = l->head;
size_t i = 1;
while (n->next != NULL) {
if (i++ == idx)
break;
n = n->next;
}
t->next = n->next;
n->next = t;
++l->elms;
++(l->elms);
return LL_SUCCESS;
}

void* ll_remove(llist_t l, size_t idx) {
if (idx >= l->elms) {
if (idx >= l->elms)
return NULL;
}

ll_node* ret = l->head;
if (idx == 0) {
l->head = ret->next;
--l->elms;
void* data = ret->data;
free(ret);
return data;
} else {
ll_node* t = NULL;
size_t i;
for (i = 0; i < idx; i++) {
t = ret;
ret = ret->next;
}
/* update the trailing "next" */
t->next = ret->next;
}
ll_node* t = NULL;
size_t i;
for (i = 0; i < idx; i++) {
t = ret;
ret = ret->next;
}
/* update the trailing "next" */
t->next = ret->next;

void* data = ret->data;
free(ret);
--l->elms;
--(l->elms);
return data;
}

2 changes: 1 addition & 1 deletion src/llist.h
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@
*** Author: Tyler Barrus
*** email: barrust@gmail.com
***
*** Version: 0.1.0
*** Version: 0.1.1
*** Purpose: Generic singly linked list implementation
***
*** License: MIT 2019
1 change: 1 addition & 0 deletions tests/doubly_linked_list_test.c
Original file line number Diff line number Diff line change
@@ -62,6 +62,7 @@ MU_TEST(test_traverse) {
*t = i;
dll_append(l, t);
}
mu_assert_int_eq(5, dll_num_elements(l));

int j = 0;
dll_node* n;