From 5f79936accdd1e56e88f68c519b7717b4f321760 Mon Sep 17 00:00:00 2001 From: jacekpoz Date: Mon, 11 Mar 2024 01:16:49 +0100 Subject: [PATCH] zad3 init --- lab01/zad3/.ccls | 21 ++++++ lab01/zad3/.gitignore | 3 + lab01/zad3/Makefile | 35 +++++++++ lab01/zad3/include/doubly_linked_list.h | 35 +++++++++ lab01/zad3/src/doubly_linked_list.c | 84 ++++++++++++++++++++++ lab01/zad3/src/main.c | 95 +++++++++++++++++++++++++ 6 files changed, 273 insertions(+) create mode 100644 lab01/zad3/.ccls create mode 100644 lab01/zad3/.gitignore create mode 100644 lab01/zad3/Makefile create mode 100644 lab01/zad3/include/doubly_linked_list.h create mode 100644 lab01/zad3/src/doubly_linked_list.c create mode 100644 lab01/zad3/src/main.c diff --git a/lab01/zad3/.ccls b/lab01/zad3/.ccls new file mode 100644 index 0000000..9f91bd0 --- /dev/null +++ b/lab01/zad3/.ccls @@ -0,0 +1,21 @@ +gcc +%c -std=c99 +%h +-Iinclude +-Wall +-Wextra +-Wpedantic +-Wstrict-aliasing +-Wfloat-equal +-Wundef +-Wshadow +-Wpointer-arith +-Wcast-align +-Wstrict-prototypes +-Wstrict-overflow=5 +-Wwrite-strings +-Wcast-qual +-Wswitch-default +-Wswitch-enum +-Wconversion +-Wunreachable-code diff --git a/lab01/zad3/.gitignore b/lab01/zad3/.gitignore new file mode 100644 index 0000000..cf48717 --- /dev/null +++ b/lab01/zad3/.gitignore @@ -0,0 +1,3 @@ +target/ +.ccls-cache/ +.direnv/ diff --git a/lab01/zad3/Makefile b/lab01/zad3/Makefile new file mode 100644 index 0000000..b42f6c0 --- /dev/null +++ b/lab01/zad3/Makefile @@ -0,0 +1,35 @@ +CC = gcc +CFLAGS = -std=c99 -O3 -Wall -Wextra -Wpedantic -Wstrict-aliasing +CFLAGS += -Wfloat-equal -Wundef -Wshadow -Wpointer-arith -Wcast-align +CFLAGS += -Wstrict-prototypes -Wstrict-overflow=5 -Wwrite-strings +CFLAGS += -Wcast-qual -Wswitch-default -Wswitch-enum +CFLAGS += -Wconversion -Wunreachable-code +CFLAGS += -Iinclude -g +LDFLAGS = + +NAME = zad3 + +SRC = src +BIN = target + +_PROG = main.c doubly_linked_list.c +PROG = $(addprefix $(SRC)/, $(_PROG)) + +OBJ = $(_PROG:.c=.o) + +.PHONY: all clean + +all: dirs $(NAME) + +dirs: + mkdir -p $(BIN) + +$(NAME): $(OBJ) + $(CC) $(addprefix $(BIN)/, $^) $(LDFLAGS) -o $(BIN)/$@ + +%.o: src/%.c + $(CC) -c $< $(CFLAGS) -o $(BIN)/$@ + +clean: + rm -rf $(addprefix $(BIN)/, $(OBJ)) + rm -rf $(BIN)/$(NAME) diff --git a/lab01/zad3/include/doubly_linked_list.h b/lab01/zad3/include/doubly_linked_list.h new file mode 100644 index 0000000..637798e --- /dev/null +++ b/lab01/zad3/include/doubly_linked_list.h @@ -0,0 +1,35 @@ +#ifndef _KIK_ZAD3_DOUBLY_LINKED_LIST_H +#define _KIK_ZAD3_DOUBLY_LINKED_LIST_H + +#include +#include + +typedef struct Node { + void *value; + struct Node *next; + struct Node *prev; +} Node; + +typedef struct { + size_t length; + size_t element_size; + Node *head; +} DoublyLinkedList; + +typedef struct { + bool success; + size_t comparisons; +} SearchResult; + +DoublyLinkedList doubly_linked_list_new(size_t element_size); + +void doubly_linked_list_insert(DoublyLinkedList *l, void *value); + +DoublyLinkedList doubly_linked_list_merge(DoublyLinkedList l1, DoublyLinkedList l2); + +// direction: +// - true = right +// - false = left +SearchResult doubly_linked_list_search(DoublyLinkedList l, void *value, bool direction, int (*compare_values)(void *v1, void *v2)); + +#endif // _KIK_ZAD3_DOUBLY_LINKED_LIST_H diff --git a/lab01/zad3/src/doubly_linked_list.c b/lab01/zad3/src/doubly_linked_list.c new file mode 100644 index 0000000..c7c9f18 --- /dev/null +++ b/lab01/zad3/src/doubly_linked_list.c @@ -0,0 +1,84 @@ +#include + +#include +#include + +Node *node_new(void *value, size_t element_size) { + Node *new = (Node*)malloc(sizeof(Node)); + new->value = memcpy(malloc(element_size), value, sizeof(element_size)); + new->next = NULL; + + return new; +} + +DoublyLinkedList doubly_linked_list_new(size_t element_size) { + DoublyLinkedList ret; + ret.length = 0; + ret.element_size = element_size; + ret.head = NULL; + + return ret; +} + +void doubly_linked_list_insert(DoublyLinkedList *l, void *value) { + if (l->head == NULL) { + l->head = node_new(value, l->element_size); + l->head->next = l->head; + l->head->prev = l->head; + l->length += 1; + return; + } + + Node *current = l->head; + while (current->next != l->head) { + current = current->next; + } + + current->next = node_new(value, l->element_size); + current->next->next = l->head; + current->next->prev = current; + l->length += 1; +} + +DoublyLinkedList doubly_linked_list_merge(DoublyLinkedList l1, DoublyLinkedList l2) { + if (l1.head == NULL) return l2; + if (l2.head == NULL) return l1; + + Node *l1_tail = l1.head; + while (l1_tail->next != l1.head) { + l1_tail = l1_tail->next; + } + + l2.head->prev = l1_tail; + l1_tail->next = l2.head; + + Node *l2_tail = l2.head; + while (l2_tail->next != l2.head) { + l2_tail = l2_tail->next; + } + + l1.head->prev = l2_tail; + l2_tail->next = l1.head; + + l1.length += l2.length; + + return l1; +} + +SearchResult doubly_linked_list_search(DoublyLinkedList l, void *value, bool direction, int (*compare_values)(void *v1, void *v2)) { + SearchResult result; + result.comparisons = 0; + result.success = false; + + Node *current = l.head; + do { + result.comparisons += 1; + if (compare_values(value, current->value) == 0) { + result.success = true; + break; + } + current = direction ? current->next : current->prev; + } while (current != l.head); + + return result; +} diff --git a/lab01/zad3/src/main.c b/lab01/zad3/src/main.c new file mode 100644 index 0000000..d4154a7 --- /dev/null +++ b/lab01/zad3/src/main.c @@ -0,0 +1,95 @@ +#include + +#include +#include +#include +#include + +void merge_test(void) { + DoublyLinkedList l1 = doubly_linked_list_new(sizeof(uint64_t)); + for (size_t i = 0; i < 10; ++i) { + uint64_t val = (uint64_t)rand() % 1000; + printf("%zu: inserting %ld into l1\n", i, val); + doubly_linked_list_insert(&l1, &val); + } + DoublyLinkedList l2 = doubly_linked_list_new(sizeof(uint64_t)); + for (size_t i = 0; i < 10; ++i) { + uint64_t val = (uint64_t)rand() % 1000; + printf("%zu: inserting %ld into l2\n", i, val); + doubly_linked_list_insert(&l2, &val); + } + + printf("merging l1 and l2\n"); + DoublyLinkedList l = doubly_linked_list_merge(l1, l2); + + Node *l_node = l.head; + size_t i = 0; + do { + uint64_t val = *(uint64_t*)l_node->value; + printf("%zu: %ld\n", i, val); + l_node = l_node->next; + i += 1; + } while (l_node != l.head); +} + +int compare_uint64_t(void *v1, void *v2) { + uint64_t u1 = *(uint64_t*)v1; + uint64_t u2 = *(uint64_t*)v2; + + if (u1 > u2) { + return 1; + } else if (u1 < u2) { + return -1; + } else { + return 0; + } +} + +const size_t T_LENGTH = 10000; +const uint64_t MAX_NUM = 100000; +const size_t TEST_ITERATIONS = 1000; + +void average_cost_test(void) { + uint64_t T[T_LENGTH]; + DoublyLinkedList L = doubly_linked_list_new(sizeof(uint64_t)); + + for (size_t i = 0; i < T_LENGTH; ++i) { + T[i] = (uint64_t)rand() % (MAX_NUM + 1); + doubly_linked_list_insert(&L, &T[i]); + } + + // searching for randomly chosen elements from T + double average_T_cost = 0.0; + // searching for randomly chosen numbers [0, 100000] + double average_rand_cost = 0.0; + + for (size_t i = 0; i < TEST_ITERATIONS; ++i) { + uint64_t t = T[(unsigned long)rand() % T_LENGTH]; + uint64_t rand_num = (uint64_t)rand() % (MAX_NUM + 1); + bool rand_direction = rand() % 2; + + SearchResult t_result = doubly_linked_list_search(L, &t, rand_direction, &compare_uint64_t); + SearchResult rand_result = doubly_linked_list_search(L, &rand_num, rand_direction, &compare_uint64_t); + + average_T_cost += (double)t_result.comparisons; + average_rand_cost += (double)rand_result.comparisons; + } + + average_T_cost /= (double)TEST_ITERATIONS; + average_rand_cost /= (double)TEST_ITERATIONS; + + printf("average search cost for randomly picked elements from T: %lf\n", average_T_cost); + printf("average search cost for randomly picked numbers from 0 to %ld: %lf\n", MAX_NUM, average_rand_cost); +} + +int main(void) { + srand((unsigned int)time(NULL)); + + merge_test(); + + printf("\n\n\n\n\n"); + + average_cost_test(); + + return 0; +}