diff --git a/05_hw/CMakeLists.txt b/05_hw/CMakeLists.txt index 6f5e398..9f7516f 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_push_pop benchmark_push_pop.c) +target_link_libraries(benchmark_push_pop stack) \ No newline at end of file diff --git a/05_hw/benchmark_push_pop.c b/05_hw/benchmark_push_pop.c new file mode 100644 index 0000000..367558d --- /dev/null +++ b/05_hw/benchmark_push_pop.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/main.c b/05_hw/main.c index fded814..917a284 100644 --- a/05_hw/main.c +++ b/05_hw/main.c @@ -18,14 +18,14 @@ int main() { printf("After popping an element:\n"); traverseStack(&stack); - Node* searchResult = searchByValue(&stack, 20); + const Node* searchResult = searchByValue(&stack, 20); if (searchResult != NULL) { printf("Element with value 20 found.\n"); } else { printf("Element with value 20 not found.\n"); } - Node* topElement = getTop(&stack); + const Node* topElement = getTop(&stack); if (topElement != NULL) { printf("Top element: %d\n", topElement->data); } diff --git a/05_hw/stack.c b/05_hw/stack.c index 0964440..c1d2696 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; } @@ -57,7 +63,7 @@ Node* searchByIndex(Stack* stack, int index) { return NULL; } -Node* getTop(Stack* stack) { +Node* getTop(const Stack* stack) { return stack->top; } @@ -71,8 +77,6 @@ void traverseStack(Stack* stack) { printf("\n"); } -bool isEmpty(Stack* stack) { - free(stack->top); +bool isEmpty(const Stack* stack) { return stack->top == NULL; -} - +} \ No newline at end of file diff --git a/05_hw/stack.h b/05_hw/stack.h index ef0734e..bc879fa 100644 --- a/05_hw/stack.h +++ b/05_hw/stack.h @@ -29,11 +29,11 @@ Node* searchByValue(Stack* stack, int value); Node* searchByIndex(Stack* stack, int index); -Node* getTop(Stack* stack); +Node* getTop(const Stack* stack); void traverseStack(Stack* stack); -bool isEmpty(Stack* stack); +bool isEmpty(const Stack* stack); #ifdef __cplusplus } diff --git a/05_hw/test_stack.c b/05_hw/test_stack.c new file mode 100644 index 0000000..98b9eaf --- /dev/null +++ b/05_hw/test_stack.c @@ -0,0 +1,183 @@ +#include "stack.h" +#include +#include +#include + +void test_push() { + Stack stack; + initStack(&stack); + + push(&stack, 10); + push(&stack, 20); + push(&stack, 30); + + // Проверяем, что верхний элемент стека - это 30 + const Node* top = getTop(&stack); + assert(top != NULL && top->data == 30); + + destroyStack(&stack); + printf("test_push: SUCCESS\n"); +} + +void test_pop() { + Stack stack; + initStack(&stack); + + push(&stack, 10); + push(&stack, 20); + push(&stack, 30); + + pop(&stack); + const Node* top = getTop(&stack); + assert(top != NULL && top->data == 20); + + pop(&stack); + top = getTop(&stack); + assert(top != NULL && top->data == 10); + + pop(&stack); + assert(isEmpty(&stack)); + + destroyStack(&stack); + printf("test_pop: SUCCESS\n"); +} + +void test_isEmpty() { + Stack stack; + initStack(&stack); + + assert(isEmpty(&stack)); + + push(&stack, 10); + assert(!isEmpty(&stack)); + + pop(&stack); + assert(isEmpty(&stack)); + + destroyStack(&stack); + printf("test_isEmpty: SUCCESS\n"); +} + +void test_searchByValue() { + Stack stack; + initStack(&stack); + + push(&stack, 10); + push(&stack, 20); + push(&stack, 30); + + const Node* result = searchByValue(&stack, 20); + assert(result != NULL && result->data == 20); + + result = searchByValue(&stack, 40); + assert(result == NULL); + + destroyStack(&stack); + printf("test_searchByValue: SUCCESS\n"); +} + +void test_searchByIndex() { + Stack stack; + initStack(&stack); + + push(&stack, 10); + push(&stack, 20); + push(&stack, 30); + + const Node* result = searchByIndex(&stack, 0); + assert(result != NULL && result->data == 30); + + result = searchByIndex(&stack, 2); + assert(result != NULL && result->data == 10); + + result = searchByIndex(&stack, 3); + assert(result == NULL); + + destroyStack(&stack); + printf("test_searchByIndex: SUCCESS\n"); +} + +void test_getTop() { + Stack stack; + initStack(&stack); + + push(&stack, 10); + push(&stack, 20); + + const Node* top = getTop(&stack); + assert(top != NULL && top->data == 20); + + pop(&stack); + top = getTop(&stack); + assert(top != NULL && top->data == 10); + + pop(&stack); + top = getTop(&stack); + assert(top == NULL); + + destroyStack(&stack); + printf("test_getTop: SUCCESS\n"); +} + +void test_destroyStack() { + Stack stack; + initStack(&stack); + + push(&stack, 10); + push(&stack, 20); + push(&stack, 30); + + destroyStack(&stack); + assert(getTop(&stack) == NULL); + + printf("test_destroyStack: SUCCESS\n"); +} + +void test_createNode() { + Node* node = createNode(42); + assert(node != NULL && node->data == 42 && node->next == NULL); + free(node); + printf("test_createNode: SUCCESS\n"); +} + +void test_initStack() { + Stack stack; + initStack(&stack); + assert(stack.top == NULL); + printf("test_initStack: SUCCESS\n"); +} + +void test_traverseStack() { + Stack stack; + initStack(&stack); + + push(&stack, 10); + push(&stack, 20); + push(&stack, 30); + + printf("Expected output: Stack elements: 30 20 10\n"); + printf("Actual output: "); + traverseStack(&stack); + + destroyStack(&stack); + printf("test_traverseStack: SUCCESS\n"); +} + +int main() { + printf("Running tests...\n"); + + test_createNode(); + test_initStack(); + test_destroyStack(); + test_push(); + test_pop(); + test_searchByValue(); + test_searchByIndex(); + test_getTop(); + test_traverseStack(); + test_isEmpty(); + + printf("All tests completed.\n"); + + return 0; +} \ No newline at end of file