From 754dadd12fbdf6846c4596c878a9cdad7d383ab1 Mon Sep 17 00:00:00 2001 From: MarcUs7i Date: Wed, 26 Mar 2025 22:10:54 +0100 Subject: [PATCH] Finished implementation --- doubly_linked_list_with_iterator.c | 216 ++++++++++++++++++++++------- 1 file changed, 165 insertions(+), 51 deletions(-) diff --git a/doubly_linked_list_with_iterator.c b/doubly_linked_list_with_iterator.c index 3e50086..6295cfc 100644 --- a/doubly_linked_list_with_iterator.c +++ b/doubly_linked_list_with_iterator.c @@ -146,7 +146,7 @@ IntList list_obtain() { * @param p_list The pointer to the list to release. The value of the pointer * is set to 0, if the list was successfully released, otherwise it is left untouched. */ -void list_release(IntList* p_list) { // no need to use the tail & size as its going to free everything anyways, TODO: check here later +void list_release(IntList* p_list) { // no need to use the tail & size as its going to free everything anyways if (p_list == 0 || *p_list == 0) { return; } @@ -211,7 +211,7 @@ int list_get_size(IntList list) { * @return `True` if the list contains at least one instance of the value, * `false ` otherwise. */ -bool list_contains(IntList list, int value) { // TODO: rewrite +bool list_contains(IntList list, int value) { if (!list_is_valid(list)) { return false; } @@ -235,19 +235,31 @@ bool list_contains(IntList list, int value) { // TODO: rewrite * @return The value stored at the given position or 0, if the position * is not available. */ -int list_get_at(IntList list, unsigned int index) { // TODO: rewrite? - if (!list_is_valid(list)) { +int list_get_at(IntList list, unsigned int index) { + if (!list_is_valid(list) || list_is_empty(list)) { return 0; } unsigned int i = 0; - IntListNode current = list->head; - while (current != 0) { - if (i == index) { - return current->data; + + // first half + if (index < list->size / 2) { + IntListNode current = list->head; + while (i < index) { + current = current->next; + i++; } - current = current->next; - i++; + return current->data; + } + // second half + else { + i = list->size - 1; + IntListNode current = list->tail; + while (i > index) { + current = current->prev; + i--; + } + return current->data; } return 0; @@ -269,9 +281,10 @@ void list_insert(IntList list, int value) { if (newNode != 0) { if (list_is_empty(list)) { list->head = newNode; + } else { + list->tail->next = newNode; + newNode->prev = list->tail; } - } else { - list->tail->next = newNode; } list->tail = newNode; @@ -289,36 +302,53 @@ void list_insert(IntList list, int value) { * @param index The position index of the value to insert. * @param value The value to insert. */ -void list_insert_at(IntList list, unsigned int index, int value) { // TODO: rewrite +void list_insert_at(IntList list, unsigned int index, int value) { if (!list_is_valid(list)) { return; } IntListNode newNode = list_obtain_node(value); + if (newNode == 0) { + return; + } if (list_is_empty(list)) { list->head = newNode; + list->tail = newNode; + list->size++; return; } if (index == 0) { newNode->next = list->head; + list->head->prev = newNode; list->head = newNode; + list->size++; return; } unsigned int i = 0; IntListNode current = list->head; - IntListNode previous = 0; - + while (current != 0 && i < index) { - previous = current; current = current->next; i++; } - previous->next = newNode; - newNode->next = current; + // if at the end, insert after current + if (current == 0) { + list->tail->next = newNode; + newNode->prev = list->tail; + list->tail = newNode; + } else { + // before current + newNode->next = current; + newNode->prev = current->prev; + current->prev->next = newNode; + current->prev = newNode; + } + + list->size++; } /** @@ -330,22 +360,24 @@ void list_insert_at(IntList list, unsigned int index, int value) { // TODO: rewr * @param list_to_append The list that is appended to `list`. */ void list_append(IntList list, IntList list_to_append) { - if (!list_is_valid(list) || !list_is_valid(list_to_append) || list_is_empty(list_to_append)) { // TODO: rewrite + if (!list_is_valid(list) || !list_is_valid(list_to_append) || list_is_empty(list_to_append)) { return; } if (list_is_empty(list)) { list->head = list_to_append->head; + list->tail = list_to_append->tail; + list->size = list_to_append->size; } else { - IntListNode current = list->head; - while (current->next != 0) { - current = current->next; - } - - current->next = list_to_append->head; + list->tail->next = list_to_append->head; + list_to_append->head->prev = list->tail; + list->tail = list_to_append->tail; + list->size += list_to_append->size; } list_to_append->head = 0; + list_to_append->tail = 0; + list_to_append->size = 0; } /** @@ -356,7 +388,7 @@ void list_append(IntList list, IntList list_to_append) { * @param list The list from which the given value shall be removed. * @param value The value to remove from the list. */ -void list_remove(IntList list, int value) { // TODO: rewrite +void list_remove(IntList list, int value) { if (!list_is_valid(list) || list_is_empty(list)) { return; } @@ -364,16 +396,33 @@ void list_remove(IntList list, int value) { // TODO: rewrite if (list->head->data == value) { IntListNode old_head = list->head; list->head = list->head->next; + + if (list->head != 0) { + list->head->prev = 0; + } else { + list->tail = 0; + } + list_release_node(old_head); + list->size--; return; } - IntListNode current = list->head; - while (current->next != 0) { - if (current->next->data == value) { - IntListNode to_remove = current->next; - current->next = to_remove->next; - list_release_node(to_remove); + IntListNode current = list->head->next; + while (current != 0) { + if (current->data == value) { + if (current->prev != 0) { + current->prev->next = current->next; + } + + if (current->next != 0) { + current->next->prev = current->prev; + } else { + list->tail = current->prev; + } + + list_release_node(current); + list->size--; return; } current = current->next; @@ -388,7 +437,7 @@ void list_remove(IntList list, int value) { // TODO: rewrite * @param list The list from which all occurrances of `value` shall be removed. * @param value The `value` to remove throughout the list. */ -void list_remove_all(IntList list, int value) { // TODO: rewrite +void list_remove_all(IntList list, int value) { if (!list_is_valid(list) || list_is_empty(list)) { return; } @@ -396,7 +445,15 @@ void list_remove_all(IntList list, int value) { // TODO: rewrite while (list->head != 0 && list->head->data == value) { IntListNode old_head = list->head; list->head = list->head->next; + + if (list->head != 0) { + list->head->prev = 0; + } else { + list->tail = 0; + } + list_release_node(old_head); + list->size--; } if (list_is_empty(list)) { @@ -404,11 +461,19 @@ void list_remove_all(IntList list, int value) { // TODO: rewrite } IntListNode current = list->head; - while (current->next != 0) { + while (current != 0 && current->next != 0) { if (current->next->data == value) { IntListNode to_remove = current->next; current->next = to_remove->next; + + if (to_remove->next != 0) { + to_remove->next->prev = current; + } else { + list->tail = current; + } + list_release_node(to_remove); + list->size--; } else { current = current->next; } @@ -424,36 +489,71 @@ void list_remove_all(IntList list, int value) { // TODO: rewrite * @param index The zero-based index of the value to return. * @return The removed value or 0 in case of errors. */ -int list_remove_at(IntList list, unsigned int index) { // TODO: rewrite - if (!list_is_valid(list) || list_is_empty(list)) { +int list_remove_at(IntList list, unsigned int index) { + if (!list_is_valid(list) || list_is_empty(list) || index >= list->size) { return 0; } + + int value; if (index == 0) { - int value = list->head->data; + value = list->head->data; IntListNode old_head = list->head; list->head = list->head->next; + + if (list->head != 0) { + list->head->prev = 0; + } else { + list->tail = 0; + } + list_release_node(old_head); + list->size--; + return value; + } + + if (index == list->size - 1) { + value = list->tail->data; + IntListNode old_tail = list->tail; + list->tail = list->tail->prev; + + list->tail->next = 0; + + list_release_node(old_tail); + list->size--; return value; } unsigned int i = 0; IntListNode current = list->head; - IntListNode previous = 0; - while (current != 0 && i < index) { - previous = current; - current = current->next; - i++; + // first half + if (index < list->size / 2) { + while (i < index) { + current = current->next; + i++; + } + // second half + } else { + current = list->tail; + i = list->size - 1; + while (i > index) { + current = current->prev; + i--; + } } - if (current == 0) { - return 0; + value = current->data; + if (current->prev != 0) { + current->prev->next = current->next; } - int value = current->data; - previous->next = current->next; + if (current->next != 0) { + current->next->prev = current->prev; + } + list_release_node(current); + list->size--; return value; } @@ -462,7 +562,7 @@ int list_remove_at(IntList list, unsigned int index) { // TODO: rewrite * * @param list The list to clear. */ -void list_clear(IntList list) { // TODO: rewrite? +void list_clear(IntList list) { if (!list_is_valid(list) || list_is_empty(list)) { return; } @@ -475,6 +575,8 @@ void list_clear(IntList list) { // TODO: rewrite? } list->head = 0; + list->tail = 0; + list->size = 0; } /* ===================================================================== */ @@ -493,7 +595,7 @@ void list_clear(IntList list) { // TODO: rewrite? * @return The list iterator instance or 0, if no list iterator could by instantiated. */ IntListIterator list_it_obtain(IntList list) { - if (!list_is_valid (list)) { + if (!list_is_valid(list)) { return 0; } @@ -515,8 +617,12 @@ IntListIterator list_it_obtain(IntList list) { * is set to 0, if the list iterator was successfully released, otherwise it is left untouched. */ void list_it_release(IntListIterator* p_it) { - free_mem(p_it); - p_it = 0; + if (p_it == 0 || *p_it == 0) { + return; + } + + free_mem(*p_it); + *p_it = 0; } /** @@ -526,7 +632,7 @@ void list_it_release(IntListIterator* p_it) { * @return `True` if the list iterator is valid, false otherwise. */ bool list_it_is_valid(IntListIterator it) { - return it != 0; + return it != 0 && it->cur != 0; } /** @@ -536,6 +642,10 @@ bool list_it_is_valid(IntListIterator it) { * @return `True` if the list iterator could proceed to the next list node, `false` otherwise. */ bool list_it_next(IntListIterator it) { + if(!list_it_is_valid(it)) { + return false; + } + if (it->cur->next == 0) { return false; } @@ -551,6 +661,10 @@ bool list_it_next(IntListIterator it) { * @return `True` if the list iterator could proceed to the previous list node, `false` otherwise. */ bool list_it_previous(IntListIterator it) { + if(!list_it_is_valid(it)) { + return false; + } + if (it->cur->prev == 0) { return false; }