142 lines
4.6 KiB
C
142 lines
4.6 KiB
C
|
#ifndef DUALCIRCULARLIST_H
|
||
|
#define DUALCIRCULARLIST_H
|
||
|
|
||
|
#include "DoublyLinkedList.h"
|
||
|
|
||
|
namespace Kylin {
|
||
|
template <typename T>
|
||
|
class CircularDoublyLinkedList : public DoublyLinkedList<T> {
|
||
|
using Node = typename DoublyLinkedList<T>::Node;
|
||
|
using Iterator = typename DoublyLinkedList<T>::Iterator;
|
||
|
|
||
|
public:
|
||
|
static constexpr size_t npos = static_cast<size_t>(-1);
|
||
|
CircularDoublyLinkedList() {
|
||
|
this->m_header.next = reinterpret_cast<Node *>(&(this->m_header));
|
||
|
this->m_header.prev = reinterpret_cast<Node *>(&(this->m_header));
|
||
|
this->m_last = reinterpret_cast<Node *>(&this->m_header);
|
||
|
}
|
||
|
|
||
|
CircularDoublyLinkedList(std::initializer_list<T> init) {
|
||
|
this->m_header.next = reinterpret_cast<Node *>(&(this->m_header));
|
||
|
this->m_header.prev = reinterpret_cast<Node *>(&(this->m_header));
|
||
|
this->m_last = reinterpret_cast<Node *>(&this->m_header);
|
||
|
for (auto &value : init) append(value);
|
||
|
}
|
||
|
|
||
|
CircularDoublyLinkedList(const CircularDoublyLinkedList &other) {
|
||
|
this->m_header.next = reinterpret_cast<Node *>(&(this->m_header));
|
||
|
this->m_header.prev = reinterpret_cast<Node *>(&(this->m_header));
|
||
|
this->m_last = reinterpret_cast<Node *>(&this->m_header);
|
||
|
|
||
|
auto sourceNode = other.m_header.next;
|
||
|
auto targetNode = reinterpret_cast<Node *>(&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<Node *>(&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<Node *>(&this->m_header)); }
|
||
|
|
||
|
Iterator end() const override { return Iterator(reinterpret_cast<Node *>(&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<Node *>(&(this->m_header));
|
||
|
for (size_t i = 0; i < index; i++) {
|
||
|
node = node->next;
|
||
|
}
|
||
|
return node;
|
||
|
}
|
||
|
};
|
||
|
} // namespace Kylin
|
||
|
#endif // DUALCIRCULARLIST_H
|