diff --git a/CMakeLists.txt b/CMakeLists.txt index fb5abf3a..3a6691b0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,7 +14,9 @@ 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_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..a6f419bd --- /dev/null +++ b/lib_doublyList/doublyList.h @@ -0,0 +1,510 @@ +#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*() { + 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) { + current = current->next; + } + 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); + 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; } + }; + + 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) {} + + 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); } + + ReverseIterator rbegin() { return ReverseIterator(_tail); } + ReverseIterator rend() { return ReverseIterator(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(); + } + + + + + + 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/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..ff1ea56a --- /dev/null +++ b/lib_list/List.h @@ -0,0 +1,279 @@ +#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() : 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; + } + + bool operator==(const Iterator& other) const { + return current == other.current; + } + + bool operator!=(const Iterator& other) const { + return current != other.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() { + 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() const; + Node* find(const T& val); + int size() const { return _count; } + +}; + +template +void List::push_front(const T& val) { + Node* node = new Node(val, _head); + + if (is_empty()) _tail = node; + + _head = node; + _count++; +} + +template +bool List::is_empty() const { + return _head == nullptr; +} + +template +void List::push_back(const T& val) { + + Node* node = new Node(val); + 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 (is_empty()) { + _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--; + } +} 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 new file mode 100644 index 00000000..6118c6cf --- /dev/null +++ b/tests/tests_List.cpp @@ -0,0 +1,153 @@ +#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(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); +} + +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(ListTest7, PopFront) { + List list; + list.push_back(1); + list.push_back(2); + list.push_back(3); + + 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(ListTest8, PopBack) { + List list; + list.push_back(1); + list.push_back(2); + list.push_back(3); + + 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(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(ListTest13, FindExisting) { + List list; + list.push_back(1); + list.push_back(2); + list.push_back(3); + + Node* found = list.find(2); + ASSERT_NE(found, nullptr); + EXPECT_EQ(found->value, 2); +} + +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); +} + 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 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 new file mode 100644 index 00000000..1f95e369 --- /dev/null +++ b/tests/tests_queue.cpp @@ -0,0 +1,141 @@ +#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); +}