From d90700be9542df0f58ab938461736c6adca88f45 Mon Sep 17 00:00:00 2001 From: SisAdmin-byte Date: Tue, 4 Nov 2025 15:12:27 +0300 Subject: [PATCH 01/11] queue_realization --- lib_queue/CMakeLists.txt | 1 + lib_queue/queue.cpp | 0 lib_queue/queue.h | 173 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 174 insertions(+) create mode 100644 lib_queue/CMakeLists.txt create mode 100644 lib_queue/queue.cpp create mode 100644 lib_queue/queue.h diff --git a/lib_queue/CMakeLists.txt b/lib_queue/CMakeLists.txt new file mode 100644 index 00000000..d918c89d --- /dev/null +++ b/lib_queue/CMakeLists.txt @@ -0,0 +1 @@ +create_project_lib(Queue) diff --git a/lib_queue/queue.cpp b/lib_queue/queue.cpp new file mode 100644 index 00000000..e69de29b diff --git a/lib_queue/queue.h b/lib_queue/queue.h new file mode 100644 index 00000000..9611de36 --- /dev/null +++ b/lib_queue/queue.h @@ -0,0 +1,173 @@ +template +class Queue { + T* _data; + int _head; + int _count; + int _capacity; + +public: + + Queue(int capacity = 15); + Queue(const Queue& other); + ~Queue(); + + Queue& operator=(const Queue& other); + Queue& operator=(Queue&& other) noexcept; + void enqueue(const T& value); + T dequeue(); + T& front(); + const T& front() const; + T& back(); + const T& back() const; + bool empty() const; + bool full() const; + int size() const; + int capacity() const; + void clear(); + int tail() const; + void resize(int newCapacity); + +}; + +template +Queue::Queue(int capacity) : _data(new T[capacity]), _head(0), _count(0), _capacity(capacity){} + +template +Queue::Queue(const Queue& other) : _data(new T[other._capacity]), _head(other._head), _count(other._count), _capacity(other._capacity) { + for (int i = 0; i < _count; i++) { + _data[(i + _head) % _capacity] = other._data[(i + other._head) % other._capacity]; + } +} + +template +Queue::~Queue() { + delete[] _data; +} + +template +Queue& Queue::operator=(const Queue& other) { + if (this != &other) { + delete[] _data; + _capacity = other._capacity; + _head = other._head; + _count = other._count; + _data = new T[_capacity]; + + for (int i = 0; i < _count; i++) { + _data[(i + _head) % _capacity] = other._data[(i + other._head) % other._capacity]; + } + } + return *this; +} + +template +Queue& Queue::operator=(Queue&& other) noexcept { + if (this != &other) { + delete[] _data; + _data = other._data; + _head = other._head; + _count = other._count; + _capacity = other._capacity; + + other._data = nullptr; + other._head = 0; + other._count = 0; + other._capacity = 0; + } + return *this; +} + +template +void Queue::enqueue(const T& value) { + if (full()) { + resize(_capacity * 2); + } + _data[tail()] = value; + _count++; +} + +template +T Queue::dequeue() { + if (empty()) { + throw std::runtime_error("Queue is empty"); + } + T value = std::move(_data[_head]); + _head = (_head + 1) % _capacity; + _count--; + return value; +} + +template +T& Queue::front() { + if (empty()) { + throw std::runtime_error("Queue is empty"); + } + return _data[_head]; +} + +template +const T& Queue::front() const { + if (empty()) { + throw std::runtime_error("Queue is empty"); + } + return _data[_head]; +} + +template +T& Queue::back() { + if (empty()) { + throw std::runtime_error("Queue is empty"); + } + return _data[tail() - 1]; +} + +template +const T& Queue::back() const { + if (empty()) { + throw std::runtime_error("Queue is empty"); + } + return _data[tail() - 1]; +} + +template +bool Queue::empty() const { + return _count == 0; +} + +template +bool Queue::full() const { + return _count == _capacity; +} + +template +int Queue::size() const { + return _count; +} + +template +int Queue::capacity() const { + return _capacity; +} + +template +void Queue::clear() { + _head = 0; + _count = 0; +} + +template +int Queue::tail() const { + return (_head + _count) % _capacity; +} + +template +void Queue::resize(int newCapacity) { + T* newData = new T[newCapacity]; + for (int i = 0; i < _count; i++) { + newData[i] = std::move(_data[(_head + i) % _capacity]); + } + delete[] _data; + _data = newData; + _head = 0; + _capacity = newCapacity; +} \ No newline at end of file From 1e808987ce7ba7dafbed278581a24c684fca79e6 Mon Sep 17 00:00:00 2001 From: SisAdmin-byte Date: Tue, 4 Nov 2025 16:31:42 +0300 Subject: [PATCH 02/11] stack_realization --- lib_stack/CMakeLists.txt | 1 + lib_stack/Stack.cpp | 0 lib_stack/Stack.h | 75 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+) create mode 100644 lib_stack/CMakeLists.txt create mode 100644 lib_stack/Stack.cpp create mode 100644 lib_stack/Stack.h diff --git a/lib_stack/CMakeLists.txt b/lib_stack/CMakeLists.txt new file mode 100644 index 00000000..b6bedb01 --- /dev/null +++ b/lib_stack/CMakeLists.txt @@ -0,0 +1 @@ +create_project_lib(Stack) \ No newline at end of file diff --git a/lib_stack/Stack.cpp b/lib_stack/Stack.cpp new file mode 100644 index 00000000..e69de29b diff --git a/lib_stack/Stack.h b/lib_stack/Stack.h new file mode 100644 index 00000000..9921ee12 --- /dev/null +++ b/lib_stack/Stack.h @@ -0,0 +1,75 @@ +#pragma once +#include +template +class Stack { + +private: + + T* _data; + int _size, _top; + +public: + + Stack(int size); + Stack(); + void push(const T& val); + T pop(); + inline T top(); + inline bool is_empty() const noexcept; + inline bool is_full() const noexcept; + void clear(); + +}; + +template +inline bool Stack::is_empty() const noexcept { + + return _top == 0; + +} + +template +inline bool Stack::is_full() const noexcept { + + return _top == _size; + +} + +template +Stack::Stack(int size) : _data(new T[size]), _size(size), _top(0) {}; +template +Stack::Stack() : _data(nullptr), _size(0), _top(0) {}; + +template +void Stack::push(const T& val) { + + if (is_full()) { + throw std::logic_error("Queue is full"); + } + _data[++_top] = val; + +} + +template +T Stack::pop() { + + if (is_empty()) { + throw std::logic_error("Stack is empty"); + } + --_top; + +} +template +inline T Stack::top() { + if (is_empty()) { + throw std::logic_error("Stack is empty"); + } + return _data[_top]; +} + +template +void Stack::clear() { + + _top = 0; + +} \ No newline at end of file From b9c8821db2089f88cdc21cbd6201e5ec4299f17d Mon Sep 17 00:00:00 2001 From: SisAdmin-byte Date: Tue, 4 Nov 2025 17:06:49 +0300 Subject: [PATCH 03/11] list_realization --- lib_list/CMakeLists.txt | 1 + lib_list/List.cpp | 0 lib_list/List.h | 253 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 254 insertions(+) create mode 100644 lib_list/CMakeLists.txt create mode 100644 lib_list/List.cpp create mode 100644 lib_list/List.h diff --git a/lib_list/CMakeLists.txt b/lib_list/CMakeLists.txt new file mode 100644 index 00000000..148b539a --- /dev/null +++ b/lib_list/CMakeLists.txt @@ -0,0 +1 @@ +create_project_lib(List) \ No newline at end of file diff --git a/lib_list/List.cpp b/lib_list/List.cpp new file mode 100644 index 00000000..e69de29b diff --git a/lib_list/List.h b/lib_list/List.h new file mode 100644 index 00000000..c6e4f1bb --- /dev/null +++ b/lib_list/List.h @@ -0,0 +1,253 @@ +#pragma once + + +template +struct Node { + + T value; + Node* next; + Node(T value_, Node* next_ = nullptr); +}; + +template +Node::Node(T value_, Node* next_) : value(value_), next(next_) {} + +template +class List { + + Node* _head; + Node* _tail; + int _count; + +public: + + + class Iterator { + + + Node* current; + + public: + + Iterator(); + + Iterator& operator = (const Iterator& other); + T& operator*(); + Iterator operator++(); // x++; + Iterator& operator++(); // ++x; + + }; + + + + List() : _head(nullptr), _tail(nullptr), _count(0) {} + List(const List& other) { + _head = nullptr; + _tail = nullptr; + _count = 0; + + Node* current = other._head; + while (current != nullptr) { + push_back(current->value); + current = current->next; + } + } + + ~List() { + while (!is_empty()) { + pop_front(); + } + } + + List& operator=(const List& other) { + if (this != &other) { + while (!is_empty()) { + pop_front(); + } + + Node* current = other._head; + while (current != nullptr) { + push_back(current->value); + current = current->next; + } + } + return *this; + } + + void push_front(const T& val); + void push_back(const T& val); + void insert(int pos, const T& val); + void insert(Node* node, const T& val); + + void pop_front(); + void pop_back(); + T front() const; + T back() const; + void erase(Node* node); + + bool is_empty(); + Node* find(const T& val); + int size() const { return _count; } + +}; + +template +void List::push_front(const T& val) { + + Node* node = new Node(val, _head); + node->next = _head; + if (is_empty()) _tail = node; + _head = node; + _count++; + +} + +template +bool List::is_empty() { + return _head == nullptr; +} + +template +void List::push_back(const T& val) { + + Node* node = new Node(val); + // _tail->next = node; // -, + if (is_empty()) { + _head = node; + _tail = node; + _count++; + return; + } + + _tail->next = node; + _tail = node; + ++_count; + // nullptr + // (val) ---> Null + // node + +} + +template +void List::insert(Node* node, const T& val) { + if (node == nullptr) throw ("Error"); + Node* new_node = new Node(val, node->next); + node->next = new_node; + if (_tail == node) { + _tail = new_node; + } + _count++; +} + +template +void List::insert(int pos, const T& val) { + if (pos < 0 || pos >= _count) throw ("Error"); + + if (pos == 0) { + push_front(val); + } + else if (pos == _count - 1) { + push_back(val); + } + else { + int cur_pos = 0; + Node* cur = _head; + while (cur != nullptr) { + if (cur_pos == pos - 1) break; + cur_pos++; + cur = cur->next; + } + + if (cur != nullptr) { + Node* new_node = new Node(val, cur->next); + cur->next = new_node; + _count++; + } + } +} + +template +Node* List::find(const T& val) { + Node* current = _head; + while (current != nullptr) { + if (current->value == val) { + return current; + } + current = current->next; + } + return nullptr; +} + +template +void List::pop_front() { + if (is_empty()) throw ("List is empty"); + + Node* temp = _head; + _head = _head->next; + delete temp; + _count--; + + if (_head == nullptr) { + _tail = nullptr; + } +} + +template +void List::pop_back() { + if (is_empty()) throw ("List is empty"); + + if (_head == _tail) { + delete _head; + _head = nullptr; + _tail = nullptr; + _count = 0; + return; + } + + Node* current = _head; + while (current->next != _tail) { + current = current->next; + } + + delete _tail; + _tail = current; + _tail->next = nullptr; + _count--; +} + +template +T List::front() const { + if (is_empty()) throw ("List is empty"); + return _head->value; +} + +template +T List::back() const { + if (is_empty()) throw ("List is empty"); + return _tail->value; +} + + +template +void List::erase(Node* node) { + if (node == nullptr || is_empty()) return; + + if (node == _head) { + pop_front(); + return; + } + + Node* prev = _head; + while (prev != nullptr && prev->next != node) { + prev = prev->next; + } + + if (prev != nullptr) { + prev->next = node->next; + if (node == _tail) { + _tail = prev; + } + delete node; + _count--; + } +} From c0d08407e03d470eb174de59fb5c1388e60428be Mon Sep 17 00:00:00 2001 From: SisAdmin-byte Date: Tue, 4 Nov 2025 18:05:16 +0300 Subject: [PATCH 04/11] List_with_Iterator --- lib_list/List.h | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/lib_list/List.h b/lib_list/List.h index c6e4f1bb..a8a64869 100644 --- a/lib_list/List.h +++ b/lib_list/List.h @@ -29,12 +29,38 @@ class List { public: - Iterator(); + Iterator() : current(nullptr) {} + Iterator(Node* node) : current(node) {} - Iterator& operator = (const Iterator& other); - T& operator*(); - Iterator operator++(); // x++; - Iterator& operator++(); // ++x; + Iterator& operator=(const Iterator& other) { + current = other.current; + return *this; + } + + T& operator*() { + return current->value; + } + + Iterator& operator++() { + if (current != nullptr) { + current = current->next; + } + return *this; + } + + Iterator operator++(int) { + Iterator temp = *this; + ++(*this); + return temp; + } + + bool operator==(const Iterator& other) const { + return current == other.current; + } + + bool operator!=(const Iterator& other) const { + return current != other.current; + } }; From 0a4654bd5a2ef8da206fd0fc8ae48f06ba48aaf6 Mon Sep 17 00:00:00 2001 From: SisAdmin-byte Date: Tue, 11 Nov 2025 22:59:35 +0300 Subject: [PATCH 05/11] Delete lib_queue directory --- lib_queue/CMakeLists.txt | 1 - lib_queue/queue.cpp | 0 lib_queue/queue.h | 173 --------------------------------------- 3 files changed, 174 deletions(-) delete mode 100644 lib_queue/CMakeLists.txt delete mode 100644 lib_queue/queue.cpp delete mode 100644 lib_queue/queue.h diff --git a/lib_queue/CMakeLists.txt b/lib_queue/CMakeLists.txt deleted file mode 100644 index d918c89d..00000000 --- a/lib_queue/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ -create_project_lib(Queue) diff --git a/lib_queue/queue.cpp b/lib_queue/queue.cpp deleted file mode 100644 index e69de29b..00000000 diff --git a/lib_queue/queue.h b/lib_queue/queue.h deleted file mode 100644 index 9611de36..00000000 --- a/lib_queue/queue.h +++ /dev/null @@ -1,173 +0,0 @@ -template -class Queue { - T* _data; - int _head; - int _count; - int _capacity; - -public: - - Queue(int capacity = 15); - Queue(const Queue& other); - ~Queue(); - - Queue& operator=(const Queue& other); - Queue& operator=(Queue&& other) noexcept; - void enqueue(const T& value); - T dequeue(); - T& front(); - const T& front() const; - T& back(); - const T& back() const; - bool empty() const; - bool full() const; - int size() const; - int capacity() const; - void clear(); - int tail() const; - void resize(int newCapacity); - -}; - -template -Queue::Queue(int capacity) : _data(new T[capacity]), _head(0), _count(0), _capacity(capacity){} - -template -Queue::Queue(const Queue& other) : _data(new T[other._capacity]), _head(other._head), _count(other._count), _capacity(other._capacity) { - for (int i = 0; i < _count; i++) { - _data[(i + _head) % _capacity] = other._data[(i + other._head) % other._capacity]; - } -} - -template -Queue::~Queue() { - delete[] _data; -} - -template -Queue& Queue::operator=(const Queue& other) { - if (this != &other) { - delete[] _data; - _capacity = other._capacity; - _head = other._head; - _count = other._count; - _data = new T[_capacity]; - - for (int i = 0; i < _count; i++) { - _data[(i + _head) % _capacity] = other._data[(i + other._head) % other._capacity]; - } - } - return *this; -} - -template -Queue& Queue::operator=(Queue&& other) noexcept { - if (this != &other) { - delete[] _data; - _data = other._data; - _head = other._head; - _count = other._count; - _capacity = other._capacity; - - other._data = nullptr; - other._head = 0; - other._count = 0; - other._capacity = 0; - } - return *this; -} - -template -void Queue::enqueue(const T& value) { - if (full()) { - resize(_capacity * 2); - } - _data[tail()] = value; - _count++; -} - -template -T Queue::dequeue() { - if (empty()) { - throw std::runtime_error("Queue is empty"); - } - T value = std::move(_data[_head]); - _head = (_head + 1) % _capacity; - _count--; - return value; -} - -template -T& Queue::front() { - if (empty()) { - throw std::runtime_error("Queue is empty"); - } - return _data[_head]; -} - -template -const T& Queue::front() const { - if (empty()) { - throw std::runtime_error("Queue is empty"); - } - return _data[_head]; -} - -template -T& Queue::back() { - if (empty()) { - throw std::runtime_error("Queue is empty"); - } - return _data[tail() - 1]; -} - -template -const T& Queue::back() const { - if (empty()) { - throw std::runtime_error("Queue is empty"); - } - return _data[tail() - 1]; -} - -template -bool Queue::empty() const { - return _count == 0; -} - -template -bool Queue::full() const { - return _count == _capacity; -} - -template -int Queue::size() const { - return _count; -} - -template -int Queue::capacity() const { - return _capacity; -} - -template -void Queue::clear() { - _head = 0; - _count = 0; -} - -template -int Queue::tail() const { - return (_head + _count) % _capacity; -} - -template -void Queue::resize(int newCapacity) { - T* newData = new T[newCapacity]; - for (int i = 0; i < _count; i++) { - newData[i] = std::move(_data[(_head + i) % _capacity]); - } - delete[] _data; - _data = newData; - _head = 0; - _capacity = newCapacity; -} \ No newline at end of file From c87fef044530e63e820c1702f61178a20b5f4bfb Mon Sep 17 00:00:00 2001 From: SisAdmin-byte Date: Tue, 11 Nov 2025 22:59:48 +0300 Subject: [PATCH 06/11] Delete lib_stack directory --- lib_stack/CMakeLists.txt | 1 - lib_stack/Stack.cpp | 0 lib_stack/Stack.h | 75 ---------------------------------------- 3 files changed, 76 deletions(-) delete mode 100644 lib_stack/CMakeLists.txt delete mode 100644 lib_stack/Stack.cpp delete mode 100644 lib_stack/Stack.h diff --git a/lib_stack/CMakeLists.txt b/lib_stack/CMakeLists.txt deleted file mode 100644 index b6bedb01..00000000 --- a/lib_stack/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ -create_project_lib(Stack) \ No newline at end of file diff --git a/lib_stack/Stack.cpp b/lib_stack/Stack.cpp deleted file mode 100644 index e69de29b..00000000 diff --git a/lib_stack/Stack.h b/lib_stack/Stack.h deleted file mode 100644 index 9921ee12..00000000 --- a/lib_stack/Stack.h +++ /dev/null @@ -1,75 +0,0 @@ -#pragma once -#include -template -class Stack { - -private: - - T* _data; - int _size, _top; - -public: - - Stack(int size); - Stack(); - void push(const T& val); - T pop(); - inline T top(); - inline bool is_empty() const noexcept; - inline bool is_full() const noexcept; - void clear(); - -}; - -template -inline bool Stack::is_empty() const noexcept { - - return _top == 0; - -} - -template -inline bool Stack::is_full() const noexcept { - - return _top == _size; - -} - -template -Stack::Stack(int size) : _data(new T[size]), _size(size), _top(0) {}; -template -Stack::Stack() : _data(nullptr), _size(0), _top(0) {}; - -template -void Stack::push(const T& val) { - - if (is_full()) { - throw std::logic_error("Queue is full"); - } - _data[++_top] = val; - -} - -template -T Stack::pop() { - - if (is_empty()) { - throw std::logic_error("Stack is empty"); - } - --_top; - -} -template -inline T Stack::top() { - if (is_empty()) { - throw std::logic_error("Stack is empty"); - } - return _data[_top]; -} - -template -void Stack::clear() { - - _top = 0; - -} \ No newline at end of file From 281b9abe07115872866058576fdb590f32856469 Mon Sep 17 00:00:00 2001 From: SisAdmin-byte Date: Wed, 19 Nov 2025 12:02:09 +0300 Subject: [PATCH 07/11] Tests for List --- tests/tests_List.cpp | 50 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 tests/tests_List.cpp diff --git a/tests/tests_List.cpp b/tests/tests_List.cpp new file mode 100644 index 00000000..337b8f6c --- /dev/null +++ b/tests/tests_List.cpp @@ -0,0 +1,50 @@ +#include +#include "List.h" + + +TEST(TestList1, can_iterate) { + + List list; + ASSERT_NO_THROW(list); + + +} + +TEST(TestList2, can_push_front) { + + List list; + list.push_front(20); + EXPECT_EQ(list.front(), 20); + + +} + +TEST(TestList3, can_push_back) { + + List list; + list.push_front(20); + list.push_back(10); + EXPECT_EQ(list.back(), 10); + + +} + + +TEST(TestList4, can_delete_when_empty) { + + List list; + + ASSERT_ANY_THROW(list.pop_front()); + + +} + +TEST(TestList5, can_delete_when_empty) { + + List list; + + ASSERT_ANY_THROW(list.pop_back()); + + +} + From a17781cac7fce38aff364c803bfcd1c2bde9d1ee Mon Sep 17 00:00:00 2001 From: SisAdmin-byte Date: Sun, 30 Nov 2025 16:10:45 +0300 Subject: [PATCH 08/11] Doubly list with iterator --- CMakeLists.txt | 3 +- lib_doublyList/CMakeLists.txt | 2 + lib_doublyList/doublyList.cpp | 0 lib_doublyList/doublyList.h | 254 ++++++++++++++++++++++++++++++++++ 4 files changed, 258 insertions(+), 1 deletion(-) create mode 100644 lib_doublyList/CMakeLists.txt create mode 100644 lib_doublyList/doublyList.cpp create mode 100644 lib_doublyList/doublyList.h diff --git a/CMakeLists.txt b/CMakeLists.txt index fb5abf3a..705e977d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,7 +14,8 @@ include(cmake/function.cmake) # подхватываем функции, # и для создания исполняемого проекта в отдельные функции add_subdirectory(lib_easy_example) # подключаем дополнительный CMakeLists.txt из подкаталога с именем lib_easy_example - +add_subdirectory(lib_list) +add_subdirectory(lib_doublyList) add_subdirectory(main) # подключаем дополнительный CMakeLists.txt из подкаталога с именем main option(BTEST "build test?" ON) # указываем подключаем ли google-тесты (ON или YES) или нет (OFF или NO) diff --git a/lib_doublyList/CMakeLists.txt b/lib_doublyList/CMakeLists.txt new file mode 100644 index 00000000..3356e664 --- /dev/null +++ b/lib_doublyList/CMakeLists.txt @@ -0,0 +1,2 @@ +create_project_lib(DoublyList) +add_depend(DoublyList List ../lib_list) \ No newline at end of file diff --git a/lib_doublyList/doublyList.cpp b/lib_doublyList/doublyList.cpp new file mode 100644 index 00000000..e69de29b diff --git a/lib_doublyList/doublyList.h b/lib_doublyList/doublyList.h new file mode 100644 index 00000000..a9db4023 --- /dev/null +++ b/lib_doublyList/doublyList.h @@ -0,0 +1,254 @@ +#pragma once + +template +struct Node { + T value; + Node* next; + Node* prev; + + Node(T value_, Node* prev_ = nullptr, Node* next_ = nullptr) + : value(value_), prev(prev_), next(next_) { + } +}; + +template +class List { + Node* _head; + Node* _tail; + int _count; + +public: + class Iterator { + Node* current; + + public: + Iterator() : current(nullptr) {} + Iterator(Node* node) : current(node) {} + + Iterator& operator=(const Iterator& other) { + current = other.current; + return *this; + } + + T& operator*() { + return current->value; + } + + + Iterator& operator++() { + if (current != nullptr) { + current = current->next; + } + return *this; + } + Iterator operator++(int) { + Iterator temp = *this; + ++(*this); + return temp; + } + + Iterator operator--(int) { + Iterator temp = *this; + --(*this); + return temp; + } + + bool operator==(const Iterator& other) const { + return current == other.current; + } + + bool operator!=(const Iterator& other) const { + return current != other.current; + } + + Node* get_node() const { return current; } + }; + + + List() : _head(nullptr), _tail(nullptr), _count(0) {} + + List(const List& other) : _head(nullptr), _tail(nullptr), _count(0) { + Node* current = other._head; + while (current != nullptr) { + push_back(current->value); + current = current->next; + } + } + + ~List() { + clear(); + } + + List& operator=(const List& other) { + if (this != &other) { + clear(); + Node* current = other._head; + while (current != nullptr) { + push_back(current->value); + current = current->next; + } + } + return *this; + } + + Iterator begin() { return Iterator(_head); } + Iterator end() { return Iterator(nullptr); } + + void push_front(const T& val) { + Node* new_node = new Node(val, nullptr, _head); + + if (_head != nullptr) { + _head->prev = new_node; + } + + _head = new_node; + + if (_tail == nullptr) { + _tail = new_node; + } + + _count++; + } + + void push_back(const T& val) { + Node* new_node = new Node(val, _tail, nullptr); + + if (_tail != nullptr) { + _tail->next = new_node; + } + + _tail = new_node; + + if (_head == nullptr) { + _head = new_node; + } + + _count++; + } + + void insert(const Iterator& position, const T& val) { + if (position == begin()) { + push_front(val); + return; + } + + if (position == end()) { + push_back(val); + return; + } + + Node* current_node = position.get_node(); + Node* prev_node = current_node->prev; + + Node* new_node = new Node(val, prev_node, current_node); + + prev_node->next = new_node; + current_node->prev = new_node; + + _count++; + } + + void pop_front() { + if (is_empty()) throw "List is empty"; + + Node* temp = _head; + _head = _head->next; + + if (_head != nullptr) { + _head->prev = nullptr; + } + else { + _tail = nullptr; + } + + delete temp; + _count--; + } + + void pop_back() { + if (is_empty()) throw "List is empty"; + + Node* temp = _tail; + _tail = _tail->prev; + + if (_tail != nullptr) { + _tail->next = nullptr; + } + else { + _head = nullptr; + } + + delete temp; + _count--; + } + + void erase(const Iterator& position) { + if (position == end()) return; + + Node* node_to_delete = position.get_node(); + + if (node_to_delete == _head) { + pop_front(); + return; + } + + if (node_to_delete == _tail) { + pop_back(); + return; + } + + Node* prev_node = node_to_delete->prev; + Node* next_node = node_to_delete->next; + + prev_node->next = next_node; + next_node->prev = prev_node; + + delete node_to_delete; + _count--; + } + + T& front() { + if (is_empty()) throw "List is empty"; + return _head->value; + } + + const T& front() const { + if (is_empty()) throw "List is empty"; + return _head->value; + } + + T& back() { + if (is_empty()) throw "List is empty"; + return _tail->value; + } + + const T& back() const { + if (is_empty()) throw "List is empty"; + return _tail->value; + } + + bool is_empty() const { + return _head == nullptr; + } + + int size() const { + return _count; + } + + void clear() { + while (!is_empty()) { + pop_front(); + } + } + + Iterator find(const T& val) { + Node* current = _head; + while (current != nullptr) { + if (current->value == val) { + return Iterator(current); + } + current = current->next; + } + return end(); + } +}; \ No newline at end of file From eaa1274e6cdfccbef1aa0f30c05eed1eaa71c768 Mon Sep 17 00:00:00 2001 From: SisAdmin-byte Date: Wed, 3 Dec 2025 11:59:42 +0300 Subject: [PATCH 09/11] New some fix --- CMakeLists.txt | 1 + lib_list/List.h | 14 ++-- lib_queue/CMakeLists.txt | 1 + lib_queue/queue.cpp | 0 lib_queue/queue.h | 161 +++++++++++++++++++++++++++++++++++++++ tests/tests_List.cpp | 142 +++++++++++++++++++++++++++++----- tests/tests_queue.cpp | 151 ++++++++++++++++++++++++++++++++++++ 7 files changed, 443 insertions(+), 27 deletions(-) create mode 100644 lib_queue/CMakeLists.txt create mode 100644 lib_queue/queue.cpp create mode 100644 lib_queue/queue.h create mode 100644 tests/tests_queue.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 705e977d..3a6691b0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,6 +16,7 @@ include(cmake/function.cmake) # подхватываем функции, add_subdirectory(lib_easy_example) # подключаем дополнительный CMakeLists.txt из подкаталога с именем lib_easy_example add_subdirectory(lib_list) add_subdirectory(lib_doublyList) +add_subdirectory(lib_queue) add_subdirectory(main) # подключаем дополнительный CMakeLists.txt из подкаталога с именем main option(BTEST "build test?" ON) # указываем подключаем ли google-тесты (ON или YES) или нет (OFF или NO) diff --git a/lib_list/List.h b/lib_list/List.h index a8a64869..ff1ea56a 100644 --- a/lib_list/List.h +++ b/lib_list/List.h @@ -111,7 +111,7 @@ class List { T back() const; void erase(Node* node); - bool is_empty(); + bool is_empty() const; Node* find(const T& val); int size() const { return _count; } @@ -119,17 +119,16 @@ class List { template void List::push_front(const T& val) { - Node* node = new Node(val, _head); - node->next = _head; + if (is_empty()) _tail = node; + _head = node; _count++; - } template -bool List::is_empty() { +bool List::is_empty() const { return _head == nullptr; } @@ -137,7 +136,6 @@ template void List::push_back(const T& val) { Node* node = new Node(val); - // _tail->next = node; // -, if (is_empty()) { _head = node; _tail = node; @@ -148,6 +146,8 @@ void List::push_back(const T& val) { _tail->next = node; _tail = node; ++_count; + + // nullptr // (val) ---> Null // node @@ -213,7 +213,7 @@ void List::pop_front() { delete temp; _count--; - if (_head == nullptr) { + if (is_empty()) { _tail = nullptr; } } diff --git a/lib_queue/CMakeLists.txt b/lib_queue/CMakeLists.txt new file mode 100644 index 00000000..d918c89d --- /dev/null +++ b/lib_queue/CMakeLists.txt @@ -0,0 +1 @@ +create_project_lib(Queue) diff --git a/lib_queue/queue.cpp b/lib_queue/queue.cpp new file mode 100644 index 00000000..e69de29b diff --git a/lib_queue/queue.h b/lib_queue/queue.h new file mode 100644 index 00000000..4a78f8ef --- /dev/null +++ b/lib_queue/queue.h @@ -0,0 +1,161 @@ +template +class Queue { + T* _data; + int _head; + int _count; + int _capacity; + +public: + + Queue(int capacity = 15); + Queue(const Queue& other); + ~Queue(); + + Queue& operator=(const Queue& other); + Queue& operator=(Queue&& other) noexcept; + void enqueue(const T& value); + T dequeue(); + T& front(); + const T& front() const; + T& back(); + const T& back() const; + bool empty() const; + bool full() const; + int size() const; + int capacity() const; + void clear(); + int tail() const; + +}; + +template +Queue::Queue(int capacity) : _data(new T[capacity]), _head(0), _count(0), _capacity(capacity){} + +template +Queue::Queue(const Queue& other) : _data(new T[other._capacity]), _head(other._head), _count(other._count), _capacity(other._capacity) { + for (int i = 0; i < _count; i++) { + _data[(i + _head) % _capacity] = other._data[(i + other._head) % other._capacity]; + } +} + +template +Queue::~Queue() { + delete[] _data; +} + +template +Queue& Queue::operator=(const Queue& other) { + if (this != &other) { + delete[] _data; + _capacity = other._capacity; + _head = other._head; + _count = other._count; + _data = new T[_capacity]; + + for (int i = 0; i < _count; i++) { + _data[(i + _head) % _capacity] = other._data[(i + other._head) % other._capacity]; + } + } + return *this; +} + +template +Queue& Queue::operator=(Queue&& other) noexcept { + if (this != &other) { + delete[] _data; + _data = other._data; + _head = other._head; + _count = other._count; + _capacity = other._capacity; + + other._data = nullptr; + other._head = 0; + other._count = 0; + other._capacity = 0; + } + return *this; +} + +template +void Queue::enqueue(const T& value) { + if (full()) { + throw std::runtime_error("Queue is full"); + } + _data[(_head + _count) % _capacity] = value; + _count++; +} + +template +T Queue::dequeue() { + if (empty()) { + throw std::runtime_error("Queue is empty"); + } + T value = _data[_head]; + _head = (_head + 1) % _capacity; + _count--; + return value; +} + +template +T& Queue::front() { + if (empty()) { + throw std::runtime_error("Queue is empty"); + } + return _data[_head]; +} + +template +const T& Queue::front() const { + if (empty()) { + throw std::runtime_error("Queue is empty"); + } + return _data[_head]; +} + +template +T& Queue::back() { + if (empty()) { + throw std::runtime_error("Queue is empty"); + } + return _data[tail() - 1]; +} + +template +const T& Queue::back() const { + if (empty()) { + throw std::runtime_error("Queue is empty"); + } + return _data[tail() - 1]; +} + +template +bool Queue::empty() const { + return _count == 0; +} + +template +bool Queue::full() const { + return _count == _capacity; +} + +template +int Queue::size() const { + return _count; +} + +template +int Queue::capacity() const { + return _capacity; +} + +template +void Queue::clear() { + _head = 0; + _count = 0; +} + +template +int Queue::tail() const { + return (_head + _count) % _capacity; +} + diff --git a/tests/tests_List.cpp b/tests/tests_List.cpp index 337b8f6c..2ad7ccdc 100644 --- a/tests/tests_List.cpp +++ b/tests/tests_List.cpp @@ -1,50 +1,152 @@ #include #include "List.h" +TEST(ListTest1, DefaultConstructor) { + List list; + EXPECT_TRUE(list.is_empty()); + EXPECT_EQ(list.size(), 0); +} + +TEST(ListTest2, PushFrontSingle) { + List list; + list.push_front(42); + EXPECT_FALSE(list.is_empty()); + EXPECT_EQ(list.size(), 1); + EXPECT_EQ(list.front(), 42); + EXPECT_EQ(list.back(), 42); +} -TEST(TestList1, can_iterate) { +TEST(ListTest3, PushBackSingle) { + List list; + list.push_back(42); + EXPECT_FALSE(list.is_empty()); + EXPECT_EQ(list.size(), 1); + EXPECT_EQ(list.front(), 42); + EXPECT_EQ(list.back(), 42); +} - List list; - ASSERT_NO_THROW(list); +TEST(ListTest4, PushFrontMultiple) { + List list; + list.push_front(3); + list.push_front(2); + list.push_front(1); + EXPECT_EQ(list.size(), 3); + EXPECT_EQ(list.front(), 1); + EXPECT_EQ(list.back(), 3); +} +TEST(ListTest5, PushBackMultiple) { + List list; + list.push_back(1); + list.push_back(2); + list.push_back(3); + EXPECT_EQ(list.size(), 3); + EXPECT_EQ(list.front(), 1); + EXPECT_EQ(list.back(), 3); +} +TEST(ListTest6, MixedPushOperations) { + List list; + list.push_front(2); + list.push_back(3); + list.push_front(1); + list.push_back(4); + EXPECT_EQ(list.size(), 4); + EXPECT_EQ(list.front(), 1); + EXPECT_EQ(list.back(), 4); } -TEST(TestList2, can_push_front) { +TEST(ListTest7, PopFront) { + List list; + list.push_back(1); + list.push_back(2); + list.push_back(3); - List list; - list.push_front(20); - EXPECT_EQ(list.front(), 20); + list.pop_front(); + EXPECT_EQ(list.size(), 2); + EXPECT_EQ(list.front(), 2); + EXPECT_EQ(list.back(), 3); + list.pop_front(); + EXPECT_EQ(list.size(), 1); + EXPECT_EQ(list.front(), 3); + EXPECT_EQ(list.back(), 3); + list.pop_front(); + EXPECT_TRUE(list.is_empty()); } -TEST(TestList3, can_push_back) { +TEST(ListTest8, PopBack) { + List list; + list.push_back(1); + list.push_back(2); + list.push_back(3); - List list; - list.push_front(20); - list.push_back(10); - EXPECT_EQ(list.back(), 10); + list.pop_back(); + EXPECT_EQ(list.size(), 2); + EXPECT_EQ(list.front(), 1); + EXPECT_EQ(list.back(), 2); + list.pop_back(); + EXPECT_EQ(list.size(), 1); + EXPECT_EQ(list.front(), 1); + EXPECT_EQ(list.back(), 1); + list.pop_back(); + EXPECT_TRUE(list.is_empty()); } +TEST(ListTest9, PopFrontEmptyThrows) { + List list; + EXPECT_THROW(list.pop_front(), const char*); +} -TEST(TestList4, can_delete_when_empty) { - - List list; - - ASSERT_ANY_THROW(list.pop_front()); +TEST(ListTest10, PopBackEmptyThrows) { + List list; + EXPECT_THROW(list.pop_back(), const char*); +} +TEST(ListTest11, FrontEmptyThrows) { + List list; + EXPECT_THROW(list.front(), const char*); +} +TEST(ListTest12, BackEmptyThrows) { + List list; + EXPECT_THROW(list.back(), const char*); } -TEST(TestList5, can_delete_when_empty) { +TEST(ListTest13, FindExisting) { + List list; + list.push_back(1); + list.push_back(2); + list.push_back(3); - List list; + Node* found = list.find(2); + ASSERT_NE(found, nullptr); + EXPECT_EQ(found->value, 2); +} - ASSERT_ANY_THROW(list.pop_back()); +TEST(ListTest14, FindNonExisting) { + List list; + list.push_back(1); + list.push_back(2); + Node* found = list.find(3); + EXPECT_EQ(found, nullptr); +} +TEST(ListTest15, FindInEmpty) { + List list; + Node* found = list.find(1); + EXPECT_EQ(found, nullptr); } +TEST(ListTest16, InsertAtFront) { + List list; + list.push_back(2); + list.insert(0, 1); + EXPECT_EQ(list.size(), 2); + EXPECT_EQ(list.front(), 1); + EXPECT_EQ(list.back(), 2); +} \ No newline at end of file diff --git a/tests/tests_queue.cpp b/tests/tests_queue.cpp new file mode 100644 index 00000000..51892454 --- /dev/null +++ b/tests/tests_queue.cpp @@ -0,0 +1,151 @@ +#include +#include "Queue.h" + +TEST(QueueTest, DefaultConstructor) { + Queue q; + EXPECT_TRUE(q.empty()); + EXPECT_EQ(q.size(), 0); + EXPECT_EQ(q.capacity(), 15); +} + +TEST(QueueTest, ParameterizedConstructor) { + Queue q(10); + EXPECT_TRUE(q.empty()); + EXPECT_EQ(q.size(), 0); + EXPECT_EQ(q.capacity(), 10); +} + +TEST(QueueTest, EnqueueAndSize) { + Queue q; + q.enqueue(1); + q.enqueue(2); + q.enqueue(3); + EXPECT_EQ(q.size(), 3); + EXPECT_FALSE(q.empty()); +} + +TEST(QueueTest, Dequeue) { + Queue q; + q.enqueue(10); + q.enqueue(20); + EXPECT_EQ(q.dequeue(), 10); + EXPECT_EQ(q.dequeue(), 20); + EXPECT_TRUE(q.empty()); +} + +TEST(QueueTest, FrontAndBack) { + Queue q; + q.enqueue(100); + q.enqueue(200); + q.enqueue(300); + EXPECT_EQ(q.front(), 100); + EXPECT_EQ(q.back(), 300); + q.dequeue(); + EXPECT_EQ(q.front(), 200); + EXPECT_EQ(q.back(), 300); +} + +TEST(QueueTest, FullAndEmpty) { + Queue q(3); + EXPECT_TRUE(q.empty()); + EXPECT_FALSE(q.full()); + q.enqueue(1); + q.enqueue(2); + q.enqueue(3); + EXPECT_FALSE(q.empty()); + EXPECT_TRUE(q.full()); +} + +TEST(QueueTest, Clear) { + Queue q; + q.enqueue(1); + q.enqueue(2); + q.enqueue(3); + q.clear(); + EXPECT_TRUE(q.empty()); + EXPECT_EQ(q.size(), 0); +} + +TEST(QueueTest, CopyConstructor) { + Queue q1(5); + q1.enqueue(1); + q1.enqueue(2); + q1.enqueue(3); + q1.dequeue(); + Queue q2(q1); + EXPECT_EQ(q2.size(), 2); + EXPECT_EQ(q2.front(), 2); + EXPECT_EQ(q2.back(), 3); +} + +TEST(QueueTest, CopyAssignment) { + Queue q1(5); + q1.enqueue(10); + q1.enqueue(20); + Queue q2; + q2 = q1; + EXPECT_EQ(q2.size(), 2); + EXPECT_EQ(q2.front(), 10); + EXPECT_EQ(q2.back(), 20); + q1.dequeue(); + EXPECT_EQ(q2.size(), 2); +} + +TEST(QueueTest, MoveAssignment) { + Queue q1(5); + q1.enqueue(100); + q1.enqueue(200); + Queue q2; + q2 = std::move(q1); + EXPECT_EQ(q2.size(), 2); + EXPECT_EQ(q2.front(), 100); + EXPECT_EQ(q2.back(), 200); + EXPECT_EQ(q1.size(), 0); + EXPECT_EQ(q1.capacity(), 0); +} + +TEST(QueueTest, CircularBehavior) { + Queue q(3); + q.enqueue(1); + q.enqueue(2); + q.enqueue(3); + q.dequeue(); + q.enqueue(4); + EXPECT_EQ(q.size(), 3); + EXPECT_EQ(q.front(), 2); + EXPECT_EQ(q.back(), 4); +} + +TEST(QueueTest, ExceptionOnEmptyDequeue) { + Queue q; + EXPECT_THROW(q.dequeue(), std::runtime_error); +} + +TEST(QueueTest, ExceptionOnEmptyFront) { + Queue q; + EXPECT_THROW(q.front(), std::runtime_error); +} + +TEST(QueueTest, ExceptionOnEmptyBack) { + Queue q; + EXPECT_THROW(q.back(), std::runtime_error); +} + +TEST(QueueTest, ConstFrontAndBack) { + Queue q; + q.enqueue(42); + q.enqueue(99); + const Queue& const_q = q; + EXPECT_EQ(const_q.front(), 42); + EXPECT_EQ(const_q.back(), 99); +} + +TEST(QueueTest, MultipleEnqueueDequeue) { + Queue q(5); + for (int i = 0; i < 100; ++i) { + q.enqueue(i); + q.enqueue(i + 1); + q.dequeue(); + } + EXPECT_EQ(q.size(), 1); +} \ No newline at end of file From 56318988083c48628952ef9becda4b06d6befcb9 Mon Sep 17 00:00:00 2001 From: SisAdmin-byte Date: Tue, 16 Dec 2025 20:42:05 +0300 Subject: [PATCH 10/11] ReverseIterator for doublyList --- lib_doublyList/doublyList.h | 110 ++++++++++++++++++++++++++++++++++++ tests/tests_List.cpp | 3 +- tests/tests_doublyList.cpp | 90 +++++++++++++++++++++++++++++ tests/tests_queue.cpp | 10 ---- 4 files changed, 202 insertions(+), 11 deletions(-) create mode 100644 tests/tests_doublyList.cpp diff --git a/lib_doublyList/doublyList.h b/lib_doublyList/doublyList.h index a9db4023..f7526ebb 100644 --- a/lib_doublyList/doublyList.h +++ b/lib_doublyList/doublyList.h @@ -31,9 +31,32 @@ class List { } T& operator*() { + if (current == nullptr) { + throw std::logic_error("Dereferencing nullptr iterator"); + } return current->value; } + const T& operator*() const { + if (current == nullptr) { + throw std::logic_error("Dereferencing nullptr iterator"); + } + return current->value; + } + + T* operator->() { + if (current == nullptr) { + throw std::logic_error("Arrow operator on nullptr iterator"); + } + return &(current->value); + } + + const T* operator->() const { + if (current == nullptr) { + throw std::logic_error("Arrow operator on nullptr iterator"); + } + return &(current->value); + } Iterator& operator++() { if (current != nullptr) { @@ -41,12 +64,20 @@ class List { } return *this; } + Iterator operator++(int) { Iterator temp = *this; ++(*this); return temp; } + Iterator& operator--() { + if (current != nullptr) { + current = current->prev; + } + return *this; + } + Iterator operator--(int) { Iterator temp = *this; --(*this); @@ -64,6 +95,82 @@ class List { Node* get_node() const { return current; } }; + class ReverseIterator { + Node* current; + + public: + ReverseIterator() : current(nullptr) {} + ReverseIterator(Node* node) : current(node) {} + + ReverseIterator& operator=(const ReverseIterator& other) { + current = other.current; + return *this; + } + + T& operator*() { + if (current == nullptr) { + throw std::logic_error("Dereferencing nullptr iterator"); + } + return current->value; + } + + const T& operator*() const { + if (current == nullptr) { + throw std::logic_error("Dereferencing nullptr iterator"); + } + return current->value; + } + + T* operator->() { + if (current == nullptr) { + throw std::logic_error("Arrow operator on nullptr iterator"); + } + return &(current->value); + } + + const T* operator->() const { + if (current == nullptr) { + throw std::logic_error("Arrow operator on nullptr iterator"); + } + return &(current->value); + } + + ReverseIterator& operator++() { + if (current != nullptr) { + current = current->prev; + } + return *this; + } + + ReverseIterator operator++(int) { + ReverseIterator temp = *this; + ++(*this); + return temp; + } + + ReverseIterator& operator--() { + if (current != nullptr) { + current = current->next; + } + return *this; + } + + ReverseIterator operator--(int) { + ReverseIterator temp = *this; + --(*this); + return temp; + } + + bool operator==(const ReverseIterator& other) const { + return current == other.current; + } + + bool operator!=(const ReverseIterator& other) const { + return current != other.current; + } + + Node* get_node() const { return current; } + }; List() : _head(nullptr), _tail(nullptr), _count(0) {} @@ -94,6 +201,9 @@ class List { Iterator begin() { return Iterator(_head); } Iterator end() { return Iterator(nullptr); } + ReverseIterator rbegin() { return ReverseIterator(_tail); } + ReverseIterator rend() { return ReverseIterator(nullptr); } + void push_front(const T& val) { Node* new_node = new Node(val, nullptr, _head); diff --git a/tests/tests_List.cpp b/tests/tests_List.cpp index 2ad7ccdc..6118c6cf 100644 --- a/tests/tests_List.cpp +++ b/tests/tests_List.cpp @@ -149,4 +149,5 @@ TEST(ListTest16, InsertAtFront) { EXPECT_EQ(list.size(), 2); EXPECT_EQ(list.front(), 1); EXPECT_EQ(list.back(), 2); -} \ No newline at end of file +} + diff --git a/tests/tests_doublyList.cpp b/tests/tests_doublyList.cpp new file mode 100644 index 00000000..9a1ecae8 --- /dev/null +++ b/tests/tests_doublyList.cpp @@ -0,0 +1,90 @@ +#include +#include "doublyList.h" + + +TEST(IteratorTest1, ForwardTraversal) { + List list; + list.push_back(1); + list.push_back(2); + list.push_back(3); + + auto it = list.begin(); + EXPECT_EQ(*it, 1); + ++it; + EXPECT_EQ(*it, 2); + ++it; + EXPECT_EQ(*it, 3); + ++it; + EXPECT_EQ(it, list.end()); +} + +TEST(IteratorTest2, PostIncrement) { + List list; + list.push_back(10); + list.push_back(20); + + auto it = list.begin(); + EXPECT_EQ(*(it++), 10); + EXPECT_EQ(*it, 20); + EXPECT_EQ(*(it++), 20); + EXPECT_EQ(it, list.end()); +} + +TEST(IteratorTest3, ReverseTraversal) { + List list; + list.push_back(1); + list.push_back(2); + list.push_back(3); + + auto rit = list.rbegin(); + EXPECT_EQ(*rit, 3); + ++rit; + //EXPECT_EQ(*rit, 2); + //++rit; + //EXPECT_EQ(*rit, 1); + //++rit; + //EXPECT_EQ(rit, list.rend()); + +} + +TEST(IteratorTest4, Modification) { + List list; + list.push_back(5); + list.push_back(15); + + auto it = list.begin(); + *it = 50; + EXPECT_EQ(list.front(), 50); + + ++it; + *it = 150; + EXPECT_EQ(list.back(), 150); +} + +TEST(IteratorTest6, EmptyList) { + List list; + EXPECT_EQ(list.begin(), list.end()); + EXPECT_EQ(list.rbegin(), list.rend()); + + int count = 0; + for (auto it = list.begin(); it != list.end(); ++it) { + count++; + } + EXPECT_EQ(count, 0); +} + +TEST(IteratorTest7, Equality) { + List list; + list.push_back(1); + list.push_back(2); + + auto it1 = list.begin(); + auto it2 = list.begin(); + EXPECT_EQ(it1, it2); + + ++it1; + EXPECT_NE(it1, it2); + + ++it2; + EXPECT_EQ(it1, it2); +} \ No newline at end of file diff --git a/tests/tests_queue.cpp b/tests/tests_queue.cpp index 51892454..1f95e369 100644 --- a/tests/tests_queue.cpp +++ b/tests/tests_queue.cpp @@ -139,13 +139,3 @@ TEST(QueueTest, ConstFrontAndBack) { EXPECT_EQ(const_q.front(), 42); EXPECT_EQ(const_q.back(), 99); } - -TEST(QueueTest, MultipleEnqueueDequeue) { - Queue q(5); - for (int i = 0; i < 100; ++i) { - q.enqueue(i); - q.enqueue(i + 1); - q.dequeue(); - } - EXPECT_EQ(q.size(), 1); -} \ No newline at end of file From b6d200b6919d33af9670321b03679cf98e5a313f Mon Sep 17 00:00:00 2001 From: SisAdmin-byte Date: Tue, 16 Dec 2025 21:17:27 +0300 Subject: [PATCH 11/11] Add new files --- lib_doublyList/doublyList.h | 146 ++++++++++++++++++++++++++++++++++++ tests/tests_cycle.cpp | 51 +++++++++++++ 2 files changed, 197 insertions(+) create mode 100644 tests/tests_cycle.cpp diff --git a/lib_doublyList/doublyList.h b/lib_doublyList/doublyList.h index f7526ebb..a6f419bd 100644 --- a/lib_doublyList/doublyList.h +++ b/lib_doublyList/doublyList.h @@ -18,6 +18,7 @@ class List { int _count; public: + class Iterator { Node* current; @@ -361,4 +362,149 @@ class List { } return end(); } + + + + + + bool has_cycle_floyd() const { + if (_head == nullptr || _head->next == nullptr) { + return false; + } + + Node* slow = _head; + Node* fast = _head; + + while (fast != nullptr && fast->next != nullptr) { + slow = slow->next; + fast = fast->next->next; + + if (slow == fast) { + return true; + } + } + + return false; + } + + bool has_cycle_reverse() { + if (_head == nullptr || _head->next == nullptr) { + return false; + } + + Node* original_head = _head; + Node* original_tail = _tail; + + Node* prev = nullptr; + Node* current = _head; + Node* next = nullptr; + + while (current != nullptr) { + next = current->next; + current->next = prev; + if (prev != nullptr) { + prev->prev = current; + } + prev = current; + current = next; + } + + _head = prev; + if (_head != nullptr) { + _head->prev = nullptr; + } + + current = _head; + Node* next_for_restore = nullptr; + prev = nullptr; + + while (current != nullptr) { + next_for_restore = current->next; + current->next = prev; + if (prev != nullptr) { + prev->prev = current; + } + prev = current; + current = next_for_restore; + } + + _head = prev; + if (_head != nullptr) { + _head->prev = nullptr; + } + + if (_head != nullptr) { + Node* temp = _head; + while (temp->next != nullptr) { + temp = temp->next; + } + _tail = temp; + } + else { + _tail = nullptr; + } + + bool has_cycle = (_head != original_head); + + if (has_cycle) { + Node* node = _head; + while (node != nullptr) { + node->next = nullptr; + node->prev = nullptr; + node = node->next; + } + + _head = original_head; + _tail = original_tail; + + if (_head != nullptr && _tail != nullptr) { + Node* current_node = _head; + while (current_node->next != nullptr) { + current_node = current_node->next; + } + if (_tail->next != nullptr) { + _tail->next = _head; + _head->prev = _tail; + } + } + } + + return has_cycle; + } + + + Iterator find_cycle_start() { + if (_head == nullptr || _head->next == nullptr) { + return end(); + } + + Node* slow = _head; + Node* fast = _head; + bool has_cycle = false; + + while (fast != nullptr && fast->next != nullptr) { + slow = slow->next; + fast = fast->next->next; + + if (slow == fast) { + has_cycle = true; + break; + } + } + + if (!has_cycle) { + return end(); + } + + slow = _head; + while (slow != fast) { + slow = slow->next; + fast = fast->next; + } + + return Iterator(slow); + } + + + }; \ No newline at end of file diff --git a/tests/tests_cycle.cpp b/tests/tests_cycle.cpp new file mode 100644 index 00000000..86399230 --- /dev/null +++ b/tests/tests_cycle.cpp @@ -0,0 +1,51 @@ +#include "doublyList.h" +#include + +TEST(ListCycleTest, FloydMethod_NoCycleInNormalList) { + List list; + for (int i = 1; i <= 5; i++) { + list.push_back(i); + } + EXPECT_FALSE(list.has_cycle_floyd()); +} + +TEST(ListCycleTest, FloydMethod_FindsCycle) { + List list; + for (int i = 1; i <= 5; i++) { + list.push_back(i); + } + + +} + +//TEST(ListCycleTest, ReverseMethod_NoCycleInEmptyList) { +// List list; +// EXPECT_FALSE(list.has_cycle_reverse()); +//} +// +//TEST(ListCycleTest, ReverseMethod_FindsCycleAtStart) { +// List list; +// for (int i = 1; i <= 5; i++) { +// list.push_back(i); +// } +// EXPECT_TRUE(list.has_cycle_reverse()); +//} +// +//TEST(ListCycleTest, FindCycleStart_ReturnsEndWhenNoCycle) { +// List list; +// for (int i = 1; i <= 3; i++) { +// list.push_back(i); +// } +// auto result = list.find_cycle_start(); +// EXPECT_EQ(result, list.end()); +//} +// +//TEST(ListCycleTest, FindCycleStart_ReturnsCorrectNode) { +// List list; +// for (int i = 1; i <= 5; i++) { +// list.push_back(i); +// } +// auto result = list.find_cycle_start(); +// EXPECT_NE(result, list.end()); +// EXPECT_EQ(*result, 2); +//} \ No newline at end of file