#ifndef DUALCIRCULARLIST_H #define DUALCIRCULARLIST_H #include "DoublyLinkedList.h" namespace Kylin { template class CircularDoublyLinkedList : public DoublyLinkedList { using Node = typename DoublyLinkedList::Node; using Iterator = typename DoublyLinkedList::Iterator; public: static constexpr size_t npos = static_cast(-1); CircularDoublyLinkedList() { this->m_header.next = reinterpret_cast(&(this->m_header)); this->m_header.prev = reinterpret_cast(&(this->m_header)); this->m_last = reinterpret_cast(&this->m_header); } CircularDoublyLinkedList(std::initializer_list init) { this->m_header.next = reinterpret_cast(&(this->m_header)); this->m_header.prev = reinterpret_cast(&(this->m_header)); this->m_last = reinterpret_cast(&this->m_header); for (auto &value : init) append(value); } CircularDoublyLinkedList(const CircularDoublyLinkedList &other) { this->m_header.next = reinterpret_cast(&(this->m_header)); this->m_header.prev = reinterpret_cast(&(this->m_header)); this->m_last = reinterpret_cast(&this->m_header); auto sourceNode = other.m_header.next; auto targetNode = reinterpret_cast(&this->m_header); for (size_t i = 0; i < other.m_size; i++) { auto newNode = this->create(); if (newNode == nullptr) THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create node ..."); newNode->value = sourceNode->value; newNode->prev = targetNode; newNode->next = targetNode->next; targetNode->next = newNode; targetNode = newNode; sourceNode = sourceNode->next; this->m_size++; this->m_last = targetNode; } } CircularDoublyLinkedList(CircularDoublyLinkedList &&other) { this->m_size = other.m_size; this->m_header = other.m_header; this->m_last = other.m_last; other.m_size = 0; other.m_header.next = nullptr; other.m_last = reinterpret_cast(&other.m_header); } void insert(size_t index, const T &value) override { index = index % (this->m_size + 1); if (index == this->m_size) return append(value); auto node = this->create(); if (node == nullptr) THROW_EXCEPTION(NoEnoughMemoryException, "No momery to insert new element..."); node->value = value; auto prev = position(index); auto next = prev->next; node->next = next; node->prev = prev; prev->next = node; next->prev = node; this->m_size++; } inline void append(const T &value) { auto node = this->create(); if (node == nullptr) THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create node ..."); node->value = value; node->prev = this->m_last; node->next = this->m_last->next; this->m_last->next->prev = node; this->m_last->next = node; this->m_last = node; this->m_size++; } void removeAt(size_t index) override { index = mod(index); auto prev = position(index); auto toDel = prev->next; auto next = toDel->next; prev->next = next; next->prev = prev; this->destroy(toDel); this->m_size--; } T &last() override { if (this->m_size <= 0) THROW_EXCEPTION(InvalidOperationException, "There is no element in the container."); return this->m_header.prev->value; } void clear() override { while (this->m_size > 0) { removeAt(0); } } Iterator end() override { return Iterator(reinterpret_cast(&this->m_header)); } Iterator end() const override { return Iterator(reinterpret_cast(&this->m_header)); } ~CircularDoublyLinkedList() { clear(); } T &operator[](size_t index) override { index = mod(index); return position(index)->next->value; } protected: size_t mod(size_t index) const { return (this->m_size == 0) ? 0 : (index % this->m_size); } Node *position(size_t index) const override { auto node = reinterpret_cast(&(this->m_header)); for (size_t i = 0; i < index; i++) { node = node->next; } return node; } }; } // namespace Kylin #endif // DUALCIRCULARLIST_H