From add23e123e01c734cf03673b0dad34da53142576 Mon Sep 17 00:00:00 2001 From: MarcUs7i Date: Wed, 14 May 2025 09:01:03 +0200 Subject: [PATCH] Done --- array_backed_list.c | 361 ++++++++++++++++++++++++++++++++- array_backed_list.h | 2 +- binary_search.c | 90 +++++++- binary_search.h | 8 +- bubble_sort.c | 53 ++++- bubble_sort.h | 14 +- insertion_sort.c | 48 ++++- insertion_sort.h | 14 +- insertion_sort_binary_search.c | 55 ++++- insertion_sort_binary_search.h | 6 +- linear_search.c | 40 +++- linear_search.h | 6 +- merge_sort.c | 69 ++++++- merge_sort.h | 14 +- quick_sort.c | 61 +++++- quick_sort.h | 6 +- sorting.c | 107 +++++++++- sorting.h | 11 +- sorting_criteria.c | 28 ++- sorting_criteria.h | 77 +++---- stopwatch.c | 74 ++++++- stopwatch.h | 4 +- test_timed_sorting | Bin 0 -> 171096 bytes 23 files changed, 1041 insertions(+), 107 deletions(-) create mode 100755 test_timed_sorting diff --git a/array_backed_list.c b/array_backed_list.c index e086502..a5ecf17 100644 --- a/array_backed_list.c +++ b/array_backed_list.c @@ -1,9 +1,9 @@ /*---------------------------------------------------------- - * HTBLA-Leonding / Class: + * HTBLA-Leonding / Class: 2IHIF * --------------------------------------------------------- * Exercise Number: S07 * Title: Array backed List implementation - * Author: */;/* + * Author: Marc Tismonar * ---------------------------------------------------------- * Description: * Implementation of an array backed list. @@ -50,6 +50,9 @@ /** The implementation of list data: payload-buffer, capacity, size */ struct IntListData { + int* buffer; + int capacity; + int size; }; /* ===================================================================== */ @@ -60,6 +63,360 @@ struct IntListData { * Hint: memcpy may be used to copy all bytes(!) from the existing to the new buffer */ static void increase_buffer(IntList list, unsigned int additional_capacity) { + if (list->buffer == 0) { + list->buffer = alloc_mem(sizeof(int) * additional_capacity); + if (list->buffer != 0) { + list->capacity = additional_capacity; + } + } else { + int* new_buffer = alloc_mem(sizeof(int) * (list->capacity + additional_capacity)); + if (new_buffer != 0) { + for (int i = 0; i < list->size; i++) { + new_buffer[i] = list->buffer[i]; + } + + free_mem(list->buffer); + list->buffer = new_buffer; + list->capacity += additional_capacity; + } + } } /* ===================================================================== */ + +/** + * 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 list = alloc_mem(sizeof(struct IntListData)); + if (list != 0) { + list->buffer = 0; + list->capacity = 0; + list->size = 0; + } + + return list; +} + +/** + * 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) { + if (p_list != 0 && *p_list != 0) { + IntList list = *p_list; + if (list->buffer != 0) { + free_mem(list->buffer); + } + + 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) { + return !list_is_valid(list) || 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) { + return list_is_valid(list) ? list->size : 0; +} + +/** + * 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) { + if (list_is_valid(list)) { + for (int i = 0; i < list->size; i++) { + if (list->buffer[i] == value) { + return true; + } + } + } + + 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) { + if (list_is_valid(list) && index < list->size) { + return list->buffer[index]; + } + + 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)) { + if (list->size >= list->capacity) { + increase_buffer(list, CAPACITY_INCREMENT); + } + + list->buffer[list->size] = value; + 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) { + if (list_is_valid(list)) { + if (index >= list->size) { + list_insert(list, value); + } else { + if (list->size >= list->capacity) { + increase_buffer(list, CAPACITY_INCREMENT); + } + + for (int i = list->size; i > index; i--) { + list->buffer[i] = list->buffer[i - 1]; + } + + list->buffer[index] = value; + list->size++; + } + } +} + +/** + * 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`. + */ +/* This function is not required in this assignment. */ +/* void list_append(IntList list, IntList list_to_append); */ + +/** + * 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) { + if (list_is_valid(list)) { + for (int i = 0; i < list->size; i++) { + if (list->buffer[i] == value) { + for (int j = i; j < list->size - 1; j++) { + list->buffer[j] = list->buffer[j + 1]; + } + + list->size--; + return; + } + } + } +} + +/** + * 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) { + if (list_is_valid(list)) { + for (int i = 0; i < list->size; i++) { + if (list->buffer[i] == value) { + for (int j = i; j < list->size - 1; j++) { + list->buffer[j] = list->buffer[j + 1]; + } + + list->size--; + i--; + } + } + } +} + +/** + * 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) { + if (list_is_valid(list) && index < list->size) { + int value = list->buffer[index]; + for (int i = index; i < list->size - 1; i++) { + list->buffer[i] = list->buffer[i + 1]; + } + + list->size--; + return value; + } + + return 0; +} + +/** + * Swaps the values at the given indexes, so that value at fst_idx becomes + * the value at snd_idx and vice versa. The invocation is ignored, if the + * list is invalid or at least one of the given indexes is out of range. + * + * @param list The list to manipulate + * @param fst_idx The index of the first item to swap. + * @param snd_idx The index of the second item to swap. + */ +void list_swap(IntList list, unsigned int fst_idx, unsigned int snd_idx) { + if (list_is_valid(list) && fst_idx < list->size && snd_idx < list->size) { + int temp = list->buffer[fst_idx]; + list->buffer[fst_idx] = list->buffer[snd_idx]; + list->buffer[snd_idx] = temp; + } +} + +/** + * Clears the given list by removing all values from the list. + * + * @param list The list to clear. + */ +void list_clear(IntList list) { + if (list_is_valid(list)) { + list->size = 0; + } +} + +/** + * 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)) { + for (int i = 0; i < list_to_append->size; i++) { + list_insert(list, list_to_append->buffer[i]); + } + list_to_append->size = 0; + } +} + +/** + * Splits the given `list` into a `left` and `right` part at the given `split_idx`. + * The `left` list contains the items of `list` from head to `split_idx - 1` rendering + * the size of the left part equal to `split_idx`. The `right` list contains + * the items of `list` from originally `split_idx` to tail. + * + * If `split_idx` is larger than the size of `list`, all items of `list` + * are moved to `left`, leaving the `right` list empty. + * + * If a target list (`left`, `right`) is not empty, the nodes that are received from + * `list` are appended. + * + * If any of the given lists is invalid, the invocation is ignored. + * + * @param list The list to split. + * @param left The left part of the original list. + * @param right The right part of the original list. + * @param split_idx The index of the node of `list` that becomes the head of `right` list. + */ +void list_split(IntList list, IntList left, IntList right, unsigned int split_idx) { + if (list_is_valid(list) && list_is_valid(left) && list_is_valid(right)) { + if (split_idx >= list->size) { + split_idx = list->size; + } + + for (int i = 0; i < split_idx; i++) { + list_insert(left, list->buffer[i]); + } + + for (int i = split_idx; i < list->size; i++) { + list_insert(right, list->buffer[i]); + } + + list_clear(list); + } +} + +/** + * Transfers the first node (the 'head') of the given `list` as last node ('tail') + * of the target list. + * + * If any of the given lists is invalid or the source list is empty, the invocation is ignored. + * + * @param list The list from which the `head` is transferred to `target_list`. + * @param target_list The list that receives the head of `list`. + */ +void list_transfer_head(IntList list, IntList target_list) { + if (list_is_valid(list) && list_is_valid(target_list) && !list_is_empty(list)) { + int value = list->buffer[0]; + list_remove_at(list, 0); + list_insert(target_list, value); + } +} \ No newline at end of file diff --git a/array_backed_list.h b/array_backed_list.h index 5d0f5cf..034072a 100644 --- a/array_backed_list.h +++ b/array_backed_list.h @@ -1,5 +1,5 @@ /*---------------------------------------------------------- - * HTBLA-Leonding / Class: + * HTBLA-Leonding / Class: 2IHIF * --------------------------------------------------------- * Exercise Number: S07 * Title: Array backed List diff --git a/binary_search.c b/binary_search.c index 60f6f67..1d1ca49 100644 --- a/binary_search.c +++ b/binary_search.c @@ -3,7 +3,7 @@ *----------------------------------------------------------------------------- * Exercise Number: S07 * Title: Binary search implementation - * Author: */;/* + * Author: Marc Tismonar *----------------------------------------------------------------------------- * Description: * Implements the binary search algorithm @@ -11,3 +11,91 @@ */ #include "binary_search.h" + +/** + * Searches the given needle within the given haystack using binary search approach. + * + * Implementation hint: delegate the invocation to function `binary_search_list_limited(…)`. + * + * @param haystack The sorted list in which the `needle` is searched. + * @param criterion The pointer to the function that implements the sorting criterion of the list. + * That function accepts two integer parameters and returns a boolean value. + * @param needle The value to find within the haystack. + * @return The index of the `needle` within the list if it was found or the position where the needle need to + * be inserted into the sorted list if it is not included in the list. The insertion position is + * expressed as index with negative sign, so that the value can be inserted at index (-1 * result). + */ +int binary_search_list(IntList haystack, criterion_fn criterion, int needle) { + if (!list_is_valid(haystack)) { + return -1; + } + + return binary_search_list_limited(haystack, list_get_size(haystack), criterion, needle); +} + +/** + * Searches the given needle within the given haystack up the given length using binary search approach. + * + * @param haystack The sorted list in which the `needle` is searched. + * @param length The number of items to consider starting from the beginning of the haystack. + * If the haystack contains more items, the remaining items are omitted from the search. If it contains + * less items, the number of items are clipped to the size of the haystack. + * @param criterion The pointer to the function that implements the sorting criterion of the list. + * That function accepts two integer parameters and returns a boolean value. + * @param needle The value to find within the haystack. + * @return The index of the `needle` within the list if it was found or the position where the needle need to + * be inserted into the sorted list if it is not included in the list. The insertion position is + * expressed as index with negative sign, so that the value can be inserted at index (-1 * result). + */ +int binary_search_list_limited(IntList haystack, int length, criterion_fn criterion, int needle) { + if (!list_is_valid(haystack) || criterion == 0) { + return -1; + } + + int list_size = list_get_size(haystack); + if (length > list_size) { + length = list_size; + } + + if (length <= 0) { + return -1; + } + + int left = 0; + int right = length - 1; + + while (left <= right) { + int mid = left + (right - left) / 2; + int mid_value = list_get_at(haystack, mid); + + if (mid_value == needle) { + return mid; + } + + if (criterion(mid_value, needle)) { + left = mid + 1; + } else { + right = mid - 1; + } + } + + return -left; +} + +/* ARRAY VARIANT */ + +/** + * Searches the given needle within the given haystack using binary search approach. + * + * @param haystack The sorted list in which the `needle` is searched. + * @param length The length of the haystack array. + * @param criterion The pointer to the function that implements the sorting criterion of the list. + * That function accepts two integer parameters and returns a boolean value. + * @param needle The value to find within the haystack. + * @return The index of the `needle` within the list if it was found or the position where the needle need to + * be inserted into the sorted list if it is not included in the list. The insertion position is + * expressed as index with negative sign, so that the value can be inserted at index (-1 * result). + */ +int binary_search_array(int haystack[], int length, criterion_fn criterion, int needle) { + return -1; +} \ No newline at end of file diff --git a/binary_search.h b/binary_search.h index ad87dfb..44c0bd4 100644 --- a/binary_search.h +++ b/binary_search.h @@ -3,7 +3,7 @@ * --------------------------------------------------------- * Exercise Number: S07 * Title: Binary search implementation - * Author: */;/* + * Author: Marc Tismonar * ---------------------------------------------------------- * Description: * Implements the binary search algorithm @@ -30,7 +30,7 @@ * be inserted into the sorted list if it is not included in the list. The insertion position is * expressed as index with negative sign, so that the value can be inserted at index (-1 * result). */ -int binary_search_list(); +int binary_search_list(IntList haystack, criterion_fn criterion, int needle); /** * Searches the given needle within the given haystack up the given length using binary search approach. @@ -46,7 +46,7 @@ int binary_search_list(); * be inserted into the sorted list if it is not included in the list. The insertion position is * expressed as index with negative sign, so that the value can be inserted at index (-1 * result). */ - binary_search_list_limited(); +int binary_search_list_limited(IntList haystack, int length, criterion_fn criterion, int needle); /* ARRAY VARIANT */ @@ -62,6 +62,6 @@ int binary_search_list(); * be inserted into the sorted list if it is not included in the list. The insertion position is * expressed as index with negative sign, so that the value can be inserted at index (-1 * result). */ - binary_search_array(); +int binary_search_array(int haystack[], int length, criterion_fn criterion, int needle); #endif diff --git a/bubble_sort.c b/bubble_sort.c index 4c6e1ab..aa535a4 100644 --- a/bubble_sort.c +++ b/bubble_sort.c @@ -1,14 +1,61 @@ /*----------------------------------------------------------------------------- * HTBLA-Leonding *----------------------------------------------------------------------------- - * Exercise Number: S07 + * Exercise Number: S05 * Title: Bubble sort implementation - * Author: */;/* + * Author: Marc Tismonar *----------------------------------------------------------------------------- * Description: - * Implements the bubble sort algorithm + * Implements the bubble sort strategy *----------------------------------------------------------------------------- */ #include "bubble_sort.h" +/** + * Sorts the given list according to the bubble sort strategy. + * + * @param list The list to be sorted. + * @param criterion The pointer to the function that implements the sorting criterion. + * That function accepts two integer parameters and returns a boolean value. + */ +void bubble_sort_list(IntList list, criterion_fn criterion) { + if (!list_is_valid(list) || criterion == 0) { + return; + } + + int size = list_get_size(list); + if (size <= 1) { + return; + } + + for (int i = 0; i < size - 1; i++) { + int swapped = 0; + + for (int j = 0; j < size - i - 1; j++) { + int current = list_get_at(list, j); + int next = list_get_at(list, j + 1); + + if (!criterion(current, next)) { + list_swap(list, j, j + 1); + swapped = 1; + } + } + + if (!swapped) { + break; + } + } +} + +/** + * Sorts the given array according to the bubble sort strategy. + * + * @param array The array to be sorted. + * @param length The length of the array. + * @param criterion The pointer to the function that implements the sorting criterion. + * That function accepts two integer parameters and returns a boolean value. + */ +void bubble_sort_array(int array[], int length, criterion_fn criterion) { + +} diff --git a/bubble_sort.h b/bubble_sort.h index 4eac554..f7480e3 100644 --- a/bubble_sort.h +++ b/bubble_sort.h @@ -1,12 +1,12 @@ /*---------------------------------------------------------- * HTBLA-Leonding * --------------------------------------------------------- - * Exercise Number: S07 + * Exercise Number: S05 * Title: Bubble sort - * Author: */;/* + * Author: Marc Tismonar * ---------------------------------------------------------- * Description: - * Implements the bubble sort algorithm + * Implements the bubble sort strategy * ---------------------------------------------------------- */ #ifndef ___BUBBLE_SORT_H @@ -18,22 +18,22 @@ /* NOTE: Either list or array variant is required! */ /** - * Sorts the given list according to the bubble sort algorithm. + * Sorts the given list according to the bubble sort strategy. * * @param list The list to be sorted. * @param criterion The pointer to the function that implements the sorting criterion. * That function accepts two integer parameters and returns a boolean value. */ -void bubble_sort_list(); +void bubble_sort_list(IntList list, criterion_fn criterion); /** - * Sorts the given array according to the bubble sort algorithm. + * Sorts the given array according to the bubble sort strategy. * * @param array The array to be sorted. * @param length The length of the array. * @param criterion The pointer to the function that implements the sorting criterion. * That function accepts two integer parameters and returns a boolean value. */ -void bubble_sort_array(); +void bubble_sort_array(int array[], int length, criterion_fn criterion); #endif diff --git a/insertion_sort.c b/insertion_sort.c index 7dd02aa..1c3a8b1 100644 --- a/insertion_sort.c +++ b/insertion_sort.c @@ -1,13 +1,53 @@ /*----------------------------------------------------------------------------- * HTBLA-Leonding *----------------------------------------------------------------------------- - * Exercise Number: S07 + * Exercise Number: S05 * Title: Insertion sort implementation - * Author: */;/* + * Author: Marc Tismonar *----------------------------------------------------------------------------- * Description: - * Implements the insertion sort algorithm + * Implements the insertion sort strategy *----------------------------------------------------------------------------- */ -#include "insertion_sort.h" \ No newline at end of file +#include "insertion_sort.h" + +/** + * Sorts the given list according to the insertion sort strategy. + * + * @param list The list to be sorted. + * @param criterion The pointer to the function that implements the sorting criterion. + * That function accepts two integer parameters and returns a boolean value. + */ +void insertion_sort_list(IntList list, criterion_fn criterion) { + if (!list_is_valid(list) || criterion == 0) { + return; + } + + int size = list_get_size(list); + if (size <= 1) { + return; + } + + for (int i = 1; i < size; i++) { + int current = list_get_at(list, i); + int j = i - 1; + + while (j >= 0 && !criterion(list_get_at(list, j), current)) { + list_swap(list, j, j + 1); + j--; + } + } +} + +/** + * Sorts the given array according to the insertion sort strategy. + * + * @param array The array to be sorted. + * @param length The length of the array. + * @param criterion The pointer to the function that implements the sorting criterion. + * That function accepts two integer parameters and returns a boolean value. + */ +void insertion_sort_array(int array[], int length, criterion_fn criterion) { + +} \ No newline at end of file diff --git a/insertion_sort.h b/insertion_sort.h index 25fc56c..bcff586 100644 --- a/insertion_sort.h +++ b/insertion_sort.h @@ -1,12 +1,12 @@ /*---------------------------------------------------------- * HTBLA-Leonding * --------------------------------------------------------- - * Exercise Number: S07 + * Exercise Number: S05 * Title: Insertion sort - * Author: */;/* + * Author: Marc Tismonar * ---------------------------------------------------------- * Description: - * Implements the insertion sort algorithm + * Implements the insertion sort strategy * ---------------------------------------------------------- */ #ifndef ___INSERTION_SORT_H @@ -18,22 +18,22 @@ /* NOTE: Either list or array variant is required! */ /** - * Sorts the given list according to the insertion sort algorithm. + * Sorts the given list according to the insertion sort strategy. * * @param list The list to be sorted. * @param criterion The pointer to the function that implements the sorting criterion. * That function accepts two integer parameters and returns a boolean value. */ -void insertion_sort_list(); +void insertion_sort_list(IntList list, criterion_fn criterion); /** - * Sorts the given array according to the insertion sort algorithm. + * Sorts the given array according to the insertion sort strategy. * * @param array The array to be sorted. * @param length The length of the array. * @param criterion The pointer to the function that implements the sorting criterion. * That function accepts two integer parameters and returns a boolean value. */ -void insertion_sort_array(); +void insertion_sort_array(int array[], int length, criterion_fn criterion); #endif diff --git a/insertion_sort_binary_search.c b/insertion_sort_binary_search.c index 4e7f418..f887188 100644 --- a/insertion_sort_binary_search.c +++ b/insertion_sort_binary_search.c @@ -3,7 +3,7 @@ *----------------------------------------------------------------------------- * Exercise Number: S07 * Title: Insertion sort implementation - * Author: */;/* + * Author: Marc Tismonar *----------------------------------------------------------------------------- * Description: * Implements the insertion sort algorithm @@ -11,3 +11,56 @@ */ #include "insertion_sort_binary_search.h" +#include "binary_search.h" + +/** + * Sorts the given list according to the insertion sort algorithm using binary. + * + * @param list The list to be sorted. + * @param criterion The pointer to the function that implements the sorting criterion. + * That function accepts two integer parameters and returns a boolean value. + */ +void insertion_sort_binsearch_list(IntList list, criterion_fn criterion) { + if (!list_is_valid(list) || criterion == 0) { + return; + } + + int size = list_get_size(list); + if (size <= 1) { + return; + } + + for (int i = 1; i < size; i++) { + int current = list_get_at(list, i); + + IntList temp = list_obtain(); + for (int k = 0; k < i; k++) { + list_insert(temp, list_get_at(list, k)); + } + + int pos = binary_search_list_limited(temp, i, criterion, current); + + if (pos < 0) { + pos = -pos; + } + + if (pos < i) { + list_remove_at(list, i); + list_insert_at(list, pos, current); + } + + list_release(&temp); + } +} + +/** + * Sorts the given array according to the insertion sort algorithm using binary search. + * + * @param array The array to be sorted. + * @param length The length of the array. + * @param criterion The pointer to the function that implements the sorting criterion. + * That function accepts two integer parameters and returns a boolean value. + */ +void insertion_sort_binsearch_array(int array[], int length, criterion_fn criterion) { + +} \ No newline at end of file diff --git a/insertion_sort_binary_search.h b/insertion_sort_binary_search.h index f6a2a0b..b17f840 100644 --- a/insertion_sort_binary_search.h +++ b/insertion_sort_binary_search.h @@ -3,7 +3,7 @@ * --------------------------------------------------------- * Exercise Number: S07 * Title: Insertion sort implementation - * Author: */;/* + * Author: Marc Tismonar * ---------------------------------------------------------- * Description: * Implements the insertion sort algorithm using binary search @@ -24,7 +24,7 @@ * @param criterion The pointer to the function that implements the sorting criterion. * That function accepts two integer parameters and returns a boolean value. */ -void insertion_sort_binsearch_list(); +void insertion_sort_binsearch_list(IntList list, criterion_fn criterion); /** * Sorts the given array according to the insertion sort algorithm using binary search. @@ -34,6 +34,6 @@ void insertion_sort_binsearch_list(); * @param criterion The pointer to the function that implements the sorting criterion. * That function accepts two integer parameters and returns a boolean value. */ -void insertion_sort_binsearch_array(); +void insertion_sort_binsearch_array(int array[], int length, criterion_fn criterion); #endif diff --git a/linear_search.c b/linear_search.c index 8eed763..2df75c6 100644 --- a/linear_search.c +++ b/linear_search.c @@ -3,7 +3,7 @@ *----------------------------------------------------------------------------- * Exercise Number: S07 * Title: Linear search implementation - * Author: */;/* + * Author: Marc Tismonar *----------------------------------------------------------------------------- * Description: * Implements the linear search algorithm @@ -12,3 +12,41 @@ #include "linear_search.h" +/** + * Searches the given needle within the given haystack using linear search approach. + * + * @param haystack The list in which the `needle` is searched. + * @param needle The value to find within the haystack. + * @return The index of the `needle` within the list or a value less than zero + * if the needle was not not found. + */ +int linear_search_list(IntList haystack, int needle) { + if (!list_is_valid(haystack)) { + return -1; + } + + int size = list_get_size(haystack); + for (int i = 0; i < size; i++) { + if (list_get_at(haystack, i) == needle) { + return i; + } + } + + return -1; +} + + +/* ARRAY VARIANT */ + +/** + * Searches the given needle within the given haystack using binary search approach. + * + * @param haystack The sorted list in which the `needle` is searched. + * @param length The length of the haystack array. + * @param needle The value to find within the haystack. + * @return The index of the `needle` within the array or a value less than zero + * if the needle was not not found. + */ +int linear_search_array(int haystack[], int length, int needle) { + return -1; +} \ No newline at end of file diff --git a/linear_search.h b/linear_search.h index f882d97..b69d6d5 100644 --- a/linear_search.h +++ b/linear_search.h @@ -3,7 +3,7 @@ * --------------------------------------------------------- * Exercise Number: S07 * Title: Linear search implementation - * Author: */;/* + * Author: Marc Tismonar * ---------------------------------------------------------- * Description: * Implements the linear search algorithm @@ -24,7 +24,7 @@ * @return The index of the `needle` within the list or a value less than zero * if the needle was not not found. */ - linear_search_list(); +int linear_search_list(IntList haystack, int needle); /* ARRAY VARIANT */ @@ -38,6 +38,6 @@ * @return The index of the `needle` within the array or a value less than zero * if the needle was not not found. */ - linear_search_array(); +int linear_search_array(int haystack[], int length, int needle); #endif diff --git a/merge_sort.c b/merge_sort.c index 2df2630..1415feb 100644 --- a/merge_sort.c +++ b/merge_sort.c @@ -1,13 +1,74 @@ /*----------------------------------------------------------------------------- * HTBLA-Leonding *----------------------------------------------------------------------------- - * Exercise Number: S07 + * Exercise Number: S06 * Title: Insertion sort implementation - * Author: */;/* + * Author: Marc Tismonar *----------------------------------------------------------------------------- * Description: - * Implements the merge sort algorithm + * Implements the merge sort strategy *----------------------------------------------------------------------------- */ -#include "merge_sort.h" \ No newline at end of file +#include "merge_sort.h" + +static void merge_sort_list_merge(IntList list, IntList left, IntList right, criterion_fn criterion) { + while (list_get_size(left) > 0 && list_get_size(right) > 0) { + if (criterion(list_get_at(left, 0), list_get_at(right, 0))) { + list_transfer_head(left, list); + } else { + list_transfer_head(right, list); + } + } + list_append(list, left); + list_append(list, right); +} + +static IntList merge_sort_list_divide_merge(IntList list, IntList result, criterion_fn criterion) { + if (list_get_size(list) <= 1) { + list_append(result, list); + return result; + } + + IntList left = list_obtain(), right = list_obtain(); + IntList left_result = list_obtain(), right_result = list_obtain(); + + list_split(list, left, right, list_get_size(list) / 2); + merge_sort_list_divide_merge(left, left_result, criterion); + merge_sort_list_divide_merge(right, right_result, criterion); + merge_sort_list_merge(result, left_result, right_result, criterion); + + list_release(&left); + list_release(&right); + list_release(&left_result); + list_release(&right_result); + + return result; +} + +/** + * Sorts the given list according to the merge sort strategy. + * + * @param list The list to be sorted. + * @param criterion The pointer to the function that implements the sorting criterion. + * That function accepts two integer parameters and returns a boolean value. + */ +void merge_sort_list(IntList list, criterion_fn criterion) { + IntList result = list_obtain(); + result = merge_sort_list_divide_merge(list, result, criterion); + list_clear(list); + list_append(list, result); + list_release(&result); +} + +/** + * Sorts the given array according to the merge sort strategy. + * + * @param array The array to be sorted. + * @param length The length of the array. + * @param criterion The pointer to the function that implements the sorting criterion. + * That function accepts two integer parameters and returns a boolean value. + */ +void merge_sort_array(int array[], int length, criterion_fn criterion) { + +} \ No newline at end of file diff --git a/merge_sort.h b/merge_sort.h index 9db5a73..cc16982 100644 --- a/merge_sort.h +++ b/merge_sort.h @@ -1,12 +1,12 @@ /*---------------------------------------------------------- * HTBLA-Leonding * --------------------------------------------------------- - * Exercise Number: S07 + * Exercise Number: S06 * Title: Insertion sort implementation - * Author: */;/* + * Author: Marc Tismonar * ---------------------------------------------------------- * Description: - * Implements the merge sort algorithm + * Implements the merge sort strategy * ---------------------------------------------------------- */ #ifndef ___MERGE_SORT_H @@ -18,22 +18,22 @@ /* NOTE: Either list or array variant is required! */ /** - * Sorts the given list according to the merge sort algorithm. + * Sorts the given list according to the merge sort strategy. * * @param list The list to be sorted. * @param criterion The pointer to the function that implements the sorting criterion. * That function accepts two integer parameters and returns a boolean value. */ -void merge_sort_list(); +void merge_sort_list(IntList list, criterion_fn criterion); /** - * Sorts the given array according to the merge sort algorithm. + * Sorts the given array according to the merge sort strategy. * * @param array The array to be sorted. * @param length The length of the array. * @param criterion The pointer to the function that implements the sorting criterion. * That function accepts two integer parameters and returns a boolean value. */ -void merge_sort_array(); +void merge_sort_array(int array[], int length, criterion_fn criterion); #endif diff --git a/quick_sort.c b/quick_sort.c index faa8745..7f056d5 100644 --- a/quick_sort.c +++ b/quick_sort.c @@ -3,7 +3,7 @@ *----------------------------------------------------------------------------- * Exercise Number: S07 * Title: Quick sort implementation - * Author: */;/* + * Author: Marc Tismonar *----------------------------------------------------------------------------- * Description: * Implements the quick sort algorithm @@ -11,3 +11,62 @@ */ #include "quick_sort.h" + +/* LIST VARIANT */ + +static int partition_list(IntList list, int low, int high, criterion_fn criterion) { + int pivot_value = list_get_at(list, high); + int i = low - 1; + + for (int j = low; j <= high - 1; j++) { + if (criterion(list_get_at(list, j), pivot_value)) { + i++; + list_swap(list, i, j); + } + } + list_swap(list, i + 1, high); + return (i + 1); +} + +static void quick_sort_list_helper(IntList list, int low, int high, criterion_fn criterion) { + if (low < high) { + int pivot_idx = partition_list(list, low, high, criterion); + + quick_sort_list_helper(list, low, pivot_idx - 1, criterion); + quick_sort_list_helper(list, pivot_idx + 1, high, criterion); + } +} + +/** + * Sorts the given list according to the quick sort algorithm. + * + * @param list The list to be sorted. + * @param criterion The pointer to the function that implements the sorting criterion. + * That function accepts two integer parameters and returns a boolean value. + */ +void quick_sort_list(IntList list, criterion_fn criterion) { + if (!list_is_valid(list) || criterion == 0) { + return; + } + + int size = list_get_size(list); + if (size <= 1) { + return; + } + + quick_sort_list_helper(list, 0, size - 1, criterion); +} + +/* ARRAY VARIANT */ + +/** + * Sorts the given array according to the quick sort algorithm. + * + * @param array The array to be sorted. + * @param length The length of the array. + * @param criterion The pointer to the function that implements the sorting criterion. + * That function accepts two integer parameters and returns a boolean value. + */ +void quick_sort_array(int array[], int length, criterion_fn criterion) { + +} diff --git a/quick_sort.h b/quick_sort.h index de70b84..3fafe08 100644 --- a/quick_sort.h +++ b/quick_sort.h @@ -3,7 +3,7 @@ * --------------------------------------------------------- * Exercise Number: S07 * Title: Quick sort - * Author: */;/* + * Author: Marc Tismonar * ---------------------------------------------------------- * Description: * Implements the quick sort algorithm @@ -24,7 +24,7 @@ * @param criterion The pointer to the function that implements the sorting criterion. * That function accepts two integer parameters and returns a boolean value. */ -void quick_sort_list(); +void quick_sort_list(IntList list, criterion_fn criterion); /** * Sorts the given array according to the quick sort algorithm. @@ -34,6 +34,6 @@ void quick_sort_list(); * @param criterion The pointer to the function that implements the sorting criterion. * That function accepts two integer parameters and returns a boolean value. */ -void quick_sort_array(); +void quick_sort_array(int array[], int length, criterion_fn criterion); #endif diff --git a/sorting.c b/sorting.c index a730f1a..a1aa8bc 100644 --- a/sorting.c +++ b/sorting.c @@ -1,9 +1,9 @@ /*----------------------------------------------------------------------------- - * HTBLA-Leonding / Class: + * HTBLA-Leonding / Class: 2IHIF *----------------------------------------------------------------------------- - * Exercise Number: S07 + * Exercise Number: S05 * Title: Sorting support functions - * Author: */;/* + * Author: Marc Tismonar *----------------------------------------------------------------------------- * Description: * Basic support functions for sorting @@ -11,6 +11,12 @@ */ #include "sorting.h" +#include +#include +#include + +#include "bubble_sort.h" +#include "insertion_sort.h" /** * This file provides some basic functions for sorting and value initialization. @@ -25,3 +31,98 @@ * Generate random values via function `random()` * Limit random value to `MAX_VALUE` as defined in `config.h` */ + +static int is_random_initialized = 0; + +/** + * Provides the name of the given sorting algorithm. + * + * @param algorithm The sorting algorithm + * @return The name of the algorithm. + */ +char* get_algorithm_name(SortingAlgorithm algorithm) { + switch (algorithm) { + case BUBBLE_SORT: + return "Bubble Sort"; + case INSERTION_SORT: + return "Insertion Sort"; + default: + return "Unknown Algorithm"; + } +} + +/** + * Initializes the given list with random elements. + * + * @param list The list to initialize. + * @param item_count The number of items to insert. + */ +void init_list_random(IntList list, int item_count) { + if (!list_is_valid(list)) { + return; + } + + if (!is_random_initialized) { + srandom(time(NULL)); + is_random_initialized = 1; + } + + list_clear(list); + + for (int i = 0; i < item_count; i++) { + int random_value = random() % (MAX_VALUE + 1); + list_insert(list, random_value); + } +} + +/** + * Prints the values stored in the given list. + * + * @param prefix The optional text to print before values are printed. + * @param list The list to dump. + */ +void print_list(char* prefix, IntList list) { + if (!list_is_valid(list)) { + return; + } + + if (prefix != NULL) { + printf("%s", prefix); + } + + printf("["); + for (int i = 0; i < list_get_size(list); i++) { + printf("%d", list_get_at(list, i)); + if (i < list_get_size(list) - 1) { + printf(", "); + } + } + printf("]\n"); +} + +/** + * Sorts the given list using the given sorting algorithm. + * + * @param list The list to sort. + * @param algorithm The sorting algorithm to use. + * @param criterion The pointer to the function that implements the sorting criterion. + * That function accepts two integer parameters and returns a boolean value. + */ +void sort_list(IntList list, SortingAlgorithm algorithm, criterion_fn criterion) { + if (!list_is_valid(list)) { + return; + } + + switch (algorithm) { + case BUBBLE_SORT: + bubble_sort_list(list, criterion); + break; + case INSERTION_SORT: + insertion_sort_list(list, criterion); + break; + default: + break; + } +} + + diff --git a/sorting.h b/sorting.h index dac6669..95b6da5 100644 --- a/sorting.h +++ b/sorting.h @@ -1,9 +1,9 @@ /*---------------------------------------------------------- * HTBLA-Leonding * --------------------------------------------------------- - * Exercise Number: S07 + * Exercise Number: S05 * Title: Sorting support functions - * Author: */;/* + * Author: Marc Tismonar * ---------------------------------------------------------- * Description: * Interface for sorting algorithms @@ -26,7 +26,6 @@ typedef enum { BUBBLE_SORT, FIRST_ALGORITHM = BUBBLE_SORT, INSERTION_SORT, - MERGE_SORT, ALGORITHM_ENUM_END } SortingAlgorithm; @@ -36,7 +35,7 @@ typedef enum { * @param algorithm The sorting algorithm * @return The name of the algorithm. */ - get_algorithm_name(); +char* get_algorithm_name(SortingAlgorithm algorithm); #ifdef LIST_VARIANT @@ -47,7 +46,7 @@ typedef enum { * @param list The list to initialize. * @param item_count The number of items to insert. */ -void init_list_random(); +void init_list_random(IntList list, int item_count); /** * Prints the values stored in the given list. @@ -65,7 +64,7 @@ void print_list(char* prefix, IntList list); * @param criterion The pointer to the function that implements the sorting criterion. * That function accepts two integer parameters and returns a boolean value. */ -void sort_list(); +void sort_list(IntList list, SortingAlgorithm algorithm, criterion_fn criterion); #else /* ARRAY_VARIANT */ diff --git a/sorting_criteria.c b/sorting_criteria.c index 6dac75f..3190c88 100644 --- a/sorting_criteria.c +++ b/sorting_criteria.c @@ -1,9 +1,9 @@ /*----------------------------------------------------------------------------- - * HTBLA-Leonding / Class: + * HTBLA-Leonding / Class: 2IHIF *----------------------------------------------------------------------------- - * Exercise Number: S07 + * Exercise Number: S05 * Title: Sorting criteria - * Author: */;/* + * Author: Marc Tismonar *----------------------------------------------------------------------------- * Description: * Implementation of sorting criteria @@ -11,3 +11,25 @@ */ #include "sorting_criteria.h" + +/** + * Determines whether or not `fst` is smaller than or equal to `snd` (ascending order). + * + * @param fst The value that is supposed being smaller than `snd`. + * @param snd The value to compare. + * @return True if `fst` is smaller than or equal to `snd`, false otherwise. + */ +bool is_in_asc_order(int fst, int snd) { + return fst <= snd; +} + +/** + * Determines whether or not `fst` is greater than or equal to `snd` (descending order). + * + * @param fst The value that is supposed being greater than `snd`. + * @param snd The value to compare. + * @return True if `fst` is greater than or equal to `snd`, false otherwise. + */ +bool is_in_desc_order(int fst, int snd) { + return fst >= snd; +} diff --git a/sorting_criteria.h b/sorting_criteria.h index 273a36f..073943f 100644 --- a/sorting_criteria.h +++ b/sorting_criteria.h @@ -1,9 +1,9 @@ /*---------------------------------------------------------- * HTBLA-Leonding * --------------------------------------------------------- - * Exercise Number: S07 + * Exercise Number: S05 * Title: Sorting criteria - * Author: */;/* + * Author: Marc Tismonar * ---------------------------------------------------------- * Description: * Interface for sorting algorithms @@ -11,39 +11,40 @@ */ -#ifndef ___SORTING_CRITERIA_H -#define ___SORTING_CRITERIA_H - -#include - -/** - * Declaration of function pointer for comparison function. - * A criterion function determines whether or not the given - * values are in the order that is defined by the criterion. - * - * @param int The value that is supposed being ordered before `snd`. - * @param int The value that is supposed being ordered after `fst`. - * @return True if `fst` IS actually ordered before `snd` - * (the values are in order), false otherwise. - */ -/* Note: Name the pointer type 'criterion_fn' */ - -/** - * Determines whether or not `fst` is smaller than or equal to `snd` (ascending order). - * - * @param fst The value that is supposed being smaller than `snd`. - * @param snd The value to compare. - * @return True if the criterion is satisfied, false otherwise. - */ - is_in_asc_order(); - -/** - * Determines whether or not `fst` is larger than or equal to `snd` (descending order). - * - * @param fst The value that is supposed being smaller than `snd`. - * @param snd The value to compare. - * @return True if the criterion is satisfied, false otherwise. - */ - is_in_desc_order(i); - -#endif \ No newline at end of file + #ifndef ___SORTING_CRITERIA_H + #define ___SORTING_CRITERIA_H + + #include + + /** + * Declaration of function pointer for comparison function. + * A criterion function determines whether or not the given + * values are in the order that is defined by the criterion. + * + * @param int The value that is supposed being ordered before `snd`. + * @param int The value that is supposed being ordered after `fst`. + * @return True if `fst` IS actually ordered before `snd` + * (the values are in order), false otherwise. + */ + /* Note: Name the pointer type 'criterion_fn' */ + typedef bool (criterion_fn)(int fst, int snd); + + /** + * Determines whether or not `fst` is smaller than or equal to `snd` (ascending order). + * + * @param fst The value that is supposed being smaller than `snd`. + * @param snd The value to compare. + * @return True if the criterion is satisfied, false otherwise. + */ + bool is_in_asc_order(int fst, int snd); + + /** + * Determines whether or not `fst` is larger than or equal to `snd` (descending order). + * + * @param fst The value that is supposed being greater than `snd`. + * @param snd The value to compare. + * @return True if the criterion is satisfied, false otherwise. + */ + bool is_in_desc_order(int fst, int snd); + + #endif \ No newline at end of file diff --git a/stopwatch.c b/stopwatch.c index 1f423db..10c19d3 100644 --- a/stopwatch.c +++ b/stopwatch.c @@ -1,9 +1,9 @@ /*----------------------------------------------------------------------------- - * HTBLA-Leonding / Class: + * HTBLA-Leonding / Class: 2IHIF *----------------------------------------------------------------------------- - * Exercise Number: S07 + * Exercise Number: S05 * Title: Stopwatch - * Author: */;/* + * Author: Marc Tismonar *----------------------------------------------------------------------------- * Description: * Implementation of a simple stopwatch @@ -25,3 +25,71 @@ * -> seconds = ticks / CLOCK_PER_SEC * microseconds are s * 10^-6 */ + +static clock_t start_time = 0; +static clock_t passed_time = 0; +static bool is_active = false; + +/** + * Starts taking the time. This function always starts at 0. + */ +void stopwatch_start() +{ + start_time = clock(); + passed_time = 0; + is_active = true; +} + +/** + * Stops or pauses taking the time. Time measurement can be resumed + * via `stopwatch_resume`. + */ +void stopwatch_stop() +{ + if (!is_active) { + return; + } + + passed_time += clock() - start_time; + is_active = false; +} + +/** + * Resumes taking the time. The previously measured time value is + * used as start value. + */ +void stopwatch_resume() +{ + if (is_active) { + return; + } + + start_time = clock(); + is_active = true; +} + +/** + * Determines whether or not the stopwatch takes the time. + * @return True if the stopwatch is measuring, false otherwise. + */ +bool stopwatch_is_active() +{ + return is_active; +} + +/** + * The measured time in microseconds. + * + * @return Either the processor time elapsed since start_stopwatch() has been called or + * the processor time elapsed between the calls of start_stopwatch() and stop_stopwatch(). + */ +double stopwatch_get_elapsed_time() +{ + clock_t total_time = passed_time; + + if (is_active) { + total_time += clock() - start_time; + } + + return ((double)total_time / CLOCKS_PER_SEC) * 1000000.0; +} \ No newline at end of file diff --git a/stopwatch.h b/stopwatch.h index 183bc70..1d9cf89 100644 --- a/stopwatch.h +++ b/stopwatch.h @@ -1,9 +1,9 @@ /*---------------------------------------------------------- * HTBLA-Leonding * --------------------------------------------------------- - * Exercise Number: S07 + * Exercise Number: S06 * Title: Stopwatch - * Author: */;/* + * Author: Marc Tismonar * ---------------------------------------------------------- * Description: * A stop watch to measure CPU time diff --git a/test_timed_sorting b/test_timed_sorting new file mode 100755 index 0000000000000000000000000000000000000000..644d5020924da5103072f5e31fd8881bb797b500 GIT binary patch literal 171096 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≈5ji>_^Sc%cT5$oUtBlSn}tkX_hwdt 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 literal 0 HcmV?d00001