Made it compile

This commit is contained in:
MarcUs7i 2025-03-26 18:32:53 +01:00
parent 003502d8dd
commit f1b24bf570
3 changed files with 535 additions and 8 deletions

View file

@ -1,9 +1,9 @@
/*---------------------------------------------------------- /*----------------------------------------------------------
* HTBLA-Leonding / Class: <your class> * HTBLA-Leonding / Class: 2IHIF
* --------------------------------------------------------- * ---------------------------------------------------------
* Exercise Number: S02 * Exercise Number: S02
* Title: Doubly Linked List implementation * Title: Doubly Linked List implementation
* Author: */<your name>;/* * Author: Marc Tismonar
* ---------------------------------------------------------- * ----------------------------------------------------------
* Description: * Description:
* Implementation of a doubly linked list. * Implementation of a doubly linked list.
@ -37,24 +37,46 @@
*/ */
#include "doubly_linked_list_with_iterator.h" #include "doubly_linked_list_with_iterator.h"
#include "limits.h"
#include "allocator.h"
/** The type of list nodes */ /** The type of list nodes */
typedef struct IntListNodeData* IntListNode;
/** The implementation of list node data */ /** The implementation of list node data */
struct IntListNodeData {
int data;
IntListNode next;
IntListNode prev;
};
/** The implementation of list data */ /** The implementation of list data */
struct IntListData {
IntListNode head;
IntListNode tail;
unsigned int size;
};
/** The implementation of list iterator data */ /** The implementation of list iterator data */
struct IntListIteratorData {
IntListNode cur;
};
/* ===================================================================== */ /* ===================================================================== */
/* private list functions */ /* private list functions */
/* abstract away and generalize also memory allocation for list nodes */ /* abstract away and generalize also memory allocation for list nodes */
static <node-type> list_obtain_node(<params>) { static IntListNode list_obtain_node(int data) {
IntListNode node = (IntListNode)alloc_mem(sizeof(struct IntListNodeData));
node->data = data;
node->next = 0;
node->prev = 0;
return node;
} }
static void list_release_node(<node-type>) { static void list_release_node(IntListNode node) {
free_mem(node);
} }
/* optional: implement a function for printing the content of the list - may be useful for debugging */ /* optional: implement a function for printing the content of the list - may be useful for debugging */
@ -62,3 +84,508 @@ void list_dump(char* prefix, IntList list) {
} }
/* ===================================================================== */ /* ===================================================================== */
/**
* Obtains ('creates') and provides a 'new' list instance.
* Any list obtained via this function MUST be released using
* function `release_list()`.
*
* Note: This function does not make any assumptions
* about how list components, esp. nodes, are allocated.
*
* @return The list instance or 0, if no list could by instantiated.
*/
IntList list_obtain() {
IntList intList = (IntList)alloc_mem(sizeof(struct IntListData));
if (intList != 0) {
intList->head = 0;
intList->tail = 0;
intList->size = 0;
}
return intList;
}
/**
* Releases a list that was obtained earlier via function `obtain_list`.
* Released lists MUST NOT be used anymore.
*
* Note: The implementation of this function does not make any assumptions
* about the allocation method of list elements, but MUST match the implementation
* of function `obtain_list` as its inverse function.
*
* @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
if (p_list == 0 || *p_list == 0) {
return;
}
IntList list = *p_list;
IntListNode current = list->head;
while (current != 0) {
IntListNode next = current->next;
list_release_node(current);
current = next;
}
free_mem(list);
*p_list = 0;
}
/**
* Determines whether or not the given list is valid.
*
* @param list The list to evaluate.
* @return `True` if the list is valid, false otherwise.
*/
bool list_is_valid(IntList list) {
return list != 0;
}
/**
* Determines whether or not the list contains at least one item.
*
* @param list The list to evaluate.
* @return `False` if the list contains one or more items, `true` otherwise.
*/
bool list_is_empty(IntList list) {
if (!list_is_valid(list)) {
return true;
}
return list->head == 0 && list->tail == 0 && list->size == 0;
}
/**
* Provides the number of values stored in the list.
*
* @param list The list to evaluate.
* @return The number of values the list contains.
*/
int list_get_size(IntList list) {
if(!list_is_empty(list)) {
return 0;
}
return list->size;
}
/**
* Determines whether or not the list given list contains the queried value
* at least once.
*
* @param list The list to query.
* @param value The value.
* @return `True` if the list contains at least one instance of the value,
* `false ` otherwise.
*/
bool list_contains(IntList list, int value) { // TODO: rewrite
if (!list_is_valid(list)) {
return false;
}
IntListNode current = list->head;
while (current != 0) {
if (current->data == value) {
return true;
}
current = current->next;
}
return false;
}
/**
* Provides the value stored in the list at the given position.
*
* @param list The list from which the value shall be retrieved.
* @param index The zero-based position index of the value to retrieve.
* @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)) {
return 0;
}
unsigned int i = 0;
IntListNode current = list->head;
while (current != 0) {
if (i == index) {
return current->data;
}
current = current->next;
i++;
}
return 0;
}
/**
* Inserts the given value at the end of the given list.
*
* @param list The list to which the value shall be appended.
* @param value The value to append to the list.
*/
void list_insert(IntList list, int value) {
if (!list_is_valid(list)) {
return;
}
IntListNode newNode = list_obtain_node(value);
if (newNode != 0) {
if (list_is_empty(list)) {
list->head = newNode;
}
} else {
list->tail->next = newNode;
}
list->tail = newNode;
list->size++;
}
/**
* Inserts the given value at the indexed position in a way the
* the inserted value is on that position. The index is
* - similar to arrays - zero-based. If the the list is shorter
* than the indexed position, the value is inserted at the end
* of the list.
*
* @param list The list into which the value shall be appended.
* @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
if (!list_is_valid(list)) {
return;
}
IntListNode newNode = list_obtain_node(value);
if (list_is_empty(list)) {
list->head = newNode;
return;
}
if (index == 0) {
newNode->next = list->head;
list->head = newNode;
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;
}
/**
* Appends the `list_to_append` at the end of the given `list`.
* The appended list is empty afterwards, because all nodes of that list
* have been transferred to `list`.
*
* @param list The list that receives the other list.
* @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
return;
}
if (list_is_empty(list)) {
list->head = list_to_append->head;
} else {
IntListNode current = list->head;
while (current->next != 0) {
current = current->next;
}
current->next = list_to_append->head;
}
list_to_append->head = 0;
}
/**
* Removes the first occurrance of `value` from the given list.
* If the list does not contain that value, the list shall not
* be modified.
*
* @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
if (!list_is_valid(list) || list_is_empty(list)) {
return;
}
if (list->head->data == value) {
IntListNode old_head = list->head;
list->head = list->head->next;
list_release_node(old_head);
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);
return;
}
current = current->next;
}
}
/**
* Removes all occurrances of `value` from the list.
* If the list does not contain that value, the list shall not
* be modified.
*
* @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
if (!list_is_valid(list) || list_is_empty(list)) {
return;
}
while (list->head != 0 && list->head->data == value) {
IntListNode old_head = list->head;
list->head = list->head->next;
list_release_node(old_head);
}
if (list_is_empty(list)) {
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);
} else {
current = current->next;
}
}
}
/**
* Removes the value at the indexed position from the given list
* and provides that value. If the list does not have a value
* at that position, the list remains unmodified.
*
* @param list The list from which the value at the given index shall be returned.
* @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)) {
return 0;
}
if (index == 0) {
int value = list->head->data;
IntListNode old_head = list->head;
list->head = list->head->next;
list_release_node(old_head);
return value;
}
unsigned int i = 0;
IntListNode current = list->head;
IntListNode previous = 0;
while (current != 0 && i < index) {
previous = current;
current = current->next;
i++;
}
if (current == 0) {
return 0;
}
int value = current->data;
previous->next = current->next;
list_release_node(current);
return value;
}
/**
* Clears the given list by removing all values from the list.
*
* @param list The list to clear.
*/
void list_clear(IntList list) { // TODO: rewrite?
if (!list_is_valid(list) || list_is_empty(list)) {
return;
}
IntListNode current = list->head;
while (current != 0) {
IntListNode next = current->next;
list_release_node(current);
current = next;
}
list->head = 0;
}
/* ===================================================================== */
/**
* Obtains ('creates') and provides a 'new' list iterator instance for the given list.
* The provided iterator initially points to the head node of the list.
*
* Any iterator obtained via this function MUST be released using
* function `release_iterator()`.
*
* Note: This function does not make any assumptions
* about how list components, esp. nodes, are allocated.
*
* @param list The list for which the iterator is obtained.
* @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)) {
return 0;
}
IntListIterator iterator = (IntListIterator)alloc_mem(sizeof(struct IntListIteratorData));
iterator->cur = list->head;
return iterator;
}
/**
* Releases a list iterator that was obtained earlier via function `list_it_obtain`.
* Released list iterators MUST NOT be used anymore.
*
* Note: The implementation of this function does not make any assumptions
* about the allocation method of list iterator elements, but MUST match the implementation
* of function `list_it_obtain` as its inverse function.
*
* @param p_it The pointer to the list iterator to release. The value of the pointer
* 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;
}
/**
* Determines whether or not the given list iterator is valid.
*
* @param it The list iterator to evaluate.
* @return `True` if the list iterator is valid, false otherwise.
*/
bool list_it_is_valid(IntListIterator it) {
return it != 0;
}
/**
* Proceeds the list iterator to the next list element, if possible.
*
* @param it The list iterator to evaluate.
* @return `True` if the list iterator could proceed to the next list node, `false` otherwise.
*/
bool list_it_next(IntListIterator it) {
if (it->cur->next == 0) {
return false;
}
it->cur = it->cur->next;
return true;
}
/**
* Proceeds the list iterator to the previous list element, if possible.
*
* @param it The list iterator to evaluate.
* @return `True` if the list iterator could proceed to the previous list node, `false` otherwise.
*/
bool list_it_previous(IntListIterator it) {
if (it->cur->prev == 0) {
return false;
}
it->cur = it->cur->prev;
return true;
}
/**
* Provides the value of the node the list iterator currently points to.
*
* @param it The list iterator to evaluate.
* @return The value of the current list node under the iterator.
*/
int list_it_get(IntListIterator it) {
if (!list_it_is_valid(it)) {
return 0;
}
return it->cur->data;
}
/**
* Applies the given value to the node the list iterator currently points to.
*
* @param it The list iterator to evaluate.
* @param value The value to set to the current list node under the iterator.
*/
void list_it_set(IntListIterator it, int value) {
if (!list_it_is_valid(it)) {
return;
}
it->cur->data = value;
}
/**
* Inserts the given value after the node under the iterator and proceeds the iterator to the
* inserted node.
*
* @param it The list iterator to evaluate.
* @param value The value to insert.
*/
void list_it_insert(IntListIterator it, int value) {
if (!list_it_is_valid(it)) {
return;
}
IntListNode newNode = list_obtain_node(value);
if (newNode != 0) {
it->cur->next = newNode;
}
}
/**
* Removes the node under the iterator and proceeds the iterator to the 'next' node.
*
* @param it The list iterator to evaluate.
*/
void list_it_remove(IntListIterator it) {
if (!list_it_is_valid(it)) {
return;
}
IntListNode nextNode = it->cur->next;
list_release_node(it->cur);
it->cur = nextNode;
}

View file

@ -1,9 +1,9 @@
/*---------------------------------------------------------- /*----------------------------------------------------------
* HTBLA-Leonding / Class: <your class> * HTBLA-Leonding / Class: 2IHIF
* --------------------------------------------------------- * ---------------------------------------------------------
* Exercise Number: S02 * Exercise Number: S02
* Title: Doubly Linked List * Title: Doubly Linked List
* Author: */<your name;/* * Author: Marc Tismonar
* ---------------------------------------------------------- * ----------------------------------------------------------
* Description: * Description:
* The declaration of a linked list abstract data type * The declaration of a linked list abstract data type

View file

@ -92,13 +92,13 @@ void list_it_set(IntListIterator it, int value);
* @param it The list iterator to evaluate. * @param it The list iterator to evaluate.
* @param value The value to insert. * @param value The value to insert.
*/ */
// void list_it_insert(IntListIterator it, int value); void list_it_insert(IntListIterator it, int value);
/** /**
* Removes the node under the iterator and proceeds the iterator to the 'next' node. * Removes the node under the iterator and proceeds the iterator to the 'next' node.
* *
* @param it The list iterator to evaluate. * @param it The list iterator to evaluate.
*/ */
// void list_it_remove(IntListIterator it); void list_it_remove(IntListIterator it);
#endif #endif