diff --git a/05_hw/CMakeLists.txt b/05_hw/CMakeLists.txt index 6f5e398..a946095 100644 --- a/05_hw/CMakeLists.txt +++ b/05_hw/CMakeLists.txt @@ -5,3 +5,12 @@ add_library(stack stack.c) add_executable(main main.c) target_link_libraries(main stack) + +add_executable(test_stack test_stack.c) +target_link_libraries(test_stack stack) + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage -g") +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage") + +add_executable(benchmark benchmark.c) +target_link_libraries(benchmark stack) \ No newline at end of file diff --git a/05_hw/benchmark.c b/05_hw/benchmark.c new file mode 100644 index 0000000..367558d --- /dev/null +++ b/05_hw/benchmark.c @@ -0,0 +1,50 @@ +#include +#include +#include +#include "stack.h" + +// Функция для проведения бенчмарков push +void benchmark_push(Stack* stack, size_t test_size) { + clock_t start = clock(); + for (size_t i = 0; i < test_size; i++) { + push(stack, (int)i); + } + clock_t end = clock(); + printf("Push %zu: %.6f seconds\n", test_size, (double)(end - start) / CLOCKS_PER_SEC); +} + +// Функция для проведения бенчмарков pop +void benchmark_pop(Stack* stack, size_t test_size) { + clock_t start = clock(); + for (size_t i = 0; i < test_size; i++) { + pop(stack); + } + clock_t end = clock(); + printf("Pop %zu: %.6f seconds\n", test_size, (double)(end - start) / CLOCKS_PER_SEC); +} + +int main() { + Stack stack; + initStack(&stack); + + // Массив с разными объемами данных + size_t test_sizes[] = { 1000000, 10000000 }; + + for (int i = 0; i < 3; i++) { + size_t test_size = test_sizes[i]; + + // Benchmark push + benchmark_push(&stack, test_size); + + // Refill stack for pop benchmark + for (size_t j = 0; j < test_size; j++) { + push(&stack, (int)j); + } + + // Benchmark pop + benchmark_pop(&stack, test_size); + } + + destroyStack(&stack); + return 0; +} diff --git a/05_hw/stack.c b/05_hw/stack.c index 0964440..c9fe6b1 100644 --- a/05_hw/stack.c +++ b/05_hw/stack.c @@ -17,10 +17,11 @@ void initStack(Stack* stack) { void destroyStack(Stack* stack) { Node* current = stack->top; while (current != NULL) { - Node *tmp = current; + Node* tmp = current; current = current->next; - free(tmp); + free(tmp); } + stack->top = NULL; // Обнуляем указатель на вершину } void push(Stack* stack, int data) { @@ -30,8 +31,12 @@ void push(Stack* stack, int data) { } void pop(Stack* stack) { + if (stack->top == NULL) { + return; // Безопасно выходим, если стек пуст + } Node* temp = stack->top; stack->top = stack->top->next; + free(temp); } Node* searchByValue(Stack* stack, int value) { @@ -40,6 +45,7 @@ Node* searchByValue(Stack* stack, int value) { if (current->data == value) { return current; } + current = current->next; // Обновляем указатель } return NULL; } @@ -72,7 +78,5 @@ void traverseStack(Stack* stack) { } bool isEmpty(Stack* stack) { - free(stack->top); return stack->top == NULL; -} - +} \ No newline at end of file diff --git a/05_hw/test_stack.c b/05_hw/test_stack.c new file mode 100644 index 0000000..adb1b52 --- /dev/null +++ b/05_hw/test_stack.c @@ -0,0 +1,184 @@ +#include "stack.h" +#include +#include +#include + +// Тест для функции добавления элементов в стек +void test_push() { + Stack stack; + initStack(&stack); + + push(&stack, 15); + push(&stack, 25); + push(&stack, 35); + + // Проверяем корректность верхнего элемента + const Node* top = getTop(&stack); + assert(top != NULL && top->data == 35); + + destroyStack(&stack); + printf("test_push: PASSED\n"); +} + +// Тест для функции удаления элементов из стека +void test_pop() { + Stack stack; + initStack(&stack); + + push(&stack, 15); + push(&stack, 25); + push(&stack, 35); + + pop(&stack); + assert(getTop(&stack)->data == 25); + + pop(&stack); + assert(getTop(&stack)->data == 15); + + pop(&stack); + assert(isEmpty(&stack)); + + destroyStack(&stack); + printf("test_pop: PASSED\n"); +} + +// Тест для проверки пустого стека +void test_isEmpty() { + Stack stack; + initStack(&stack); + + assert(isEmpty(&stack)); // Стек пуст при инициализации + + push(&stack, 42); + assert(!isEmpty(&stack)); // Стек больше не пуст + + pop(&stack); + assert(isEmpty(&stack)); // После удаления стек снова пуст + + destroyStack(&stack); + printf("test_isEmpty: PASSED\n"); +} + +// Тест для поиска по значению +void test_searchByValue() { + Stack stack; + initStack(&stack); + + push(&stack, 5); + push(&stack, 15); + push(&stack, 25); + + const Node* found = searchByValue(&stack, 15); + assert(found != NULL && found->data == 15); + + found = searchByValue(&stack, 99); + assert(found == NULL); + + destroyStack(&stack); + printf("test_searchByValue: PASSED\n"); +} + +// Тест для поиска по индексу +void test_searchByIndex() { + Stack stack; + initStack(&stack); + + push(&stack, 10); + push(&stack, 20); + push(&stack, 30); + + const Node* result = searchByIndex(&stack, 1); + assert(result != NULL && result->data == 20); + + result = searchByIndex(&stack, 5); + assert(result == NULL); + + destroyStack(&stack); + printf("test_searchByIndex: PASSED\n"); +} + +// Тест для функции получения верхнего элемента +void test_getTop() { + Stack stack; + initStack(&stack); + + push(&stack, 8); + push(&stack, 18); + + const Node* top = getTop(&stack); + assert(top != NULL && top->data == 18); + + pop(&stack); + assert(getTop(&stack)->data == 8); + + destroyStack(&stack); + printf("test_getTop: PASSED\n"); +} + +// Тест для корректного освобождения памяти +void test_destroyStack() { + Stack stack; + initStack(&stack); + + push(&stack, 1); + push(&stack, 2); + + destroyStack(&stack); + assert(getTop(&stack) == NULL); + + printf("test_destroyStack: PASSED\n"); +} + +// Тест для создания узла +void test_createNode() { + Node* node = createNode(100); + assert(node != NULL && node->data == 100 && node->next == NULL); + + free(node); + printf("test_createNode: PASSED\n"); +} + +// Тест для инициализации стека +void test_initStack() { + Stack stack; + initStack(&stack); + assert(stack.top == NULL); + + printf("test_initStack: PASSED\n"); +} + +// Тест для отображения содержимого стека +void test_traverseStack() { + Stack stack; + initStack(&stack); + + push(&stack, 3); + push(&stack, 6); + push(&stack, 9); + + printf("Expected output: 9 6 3\n"); + printf("Actual output: "); + traverseStack(&stack); + + destroyStack(&stack); + printf("test_traverseStack: PASSED\n"); +} + +// Главная функция для запуска всех тестов +int main() { + printf("Starting test suite...\n"); + + test_createNode(); + test_initStack(); + test_destroyStack(); + test_push(); + test_pop(); + test_isEmpty(); + test_searchByValue(); + test_searchByIndex(); + test_getTop(); + test_traverseStack(); + + printf("All tests completed successfully.\n"); + return 0; +}