zad3 init
This commit is contained in:
parent
25c4656a51
commit
5f79936acc
6 changed files with 273 additions and 0 deletions
21
lab01/zad3/.ccls
Normal file
21
lab01/zad3/.ccls
Normal file
|
@ -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
|
3
lab01/zad3/.gitignore
vendored
Normal file
3
lab01/zad3/.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
target/
|
||||||
|
.ccls-cache/
|
||||||
|
.direnv/
|
35
lab01/zad3/Makefile
Normal file
35
lab01/zad3/Makefile
Normal file
|
@ -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)
|
35
lab01/zad3/include/doubly_linked_list.h
Normal file
35
lab01/zad3/include/doubly_linked_list.h
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
#ifndef _KIK_ZAD3_DOUBLY_LINKED_LIST_H
|
||||||
|
#define _KIK_ZAD3_DOUBLY_LINKED_LIST_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
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
|
84
lab01/zad3/src/doubly_linked_list.c
Normal file
84
lab01/zad3/src/doubly_linked_list.c
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
#include <doubly_linked_list.h>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
95
lab01/zad3/src/main.c
Normal file
95
lab01/zad3/src/main.c
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
#include <doubly_linked_list.h>
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
Loading…
Reference in a new issue