#ifndef LINKEDLIST_H #define LINKEDLIST_H #include "Exception.h" #include "List.h" #include namespace Kylin { template class LinkedList : public List { protected: struct Node : public Object { T value; Node *next = nullptr; }; struct : public Object { char reserved[sizeof(T)]; Node *next = nullptr; } mutable m_header; public: class Iterator : public Object { friend class LinkedList; public: Iterator() = default; Iterator(Node *pos) : pos(pos) {} Iterator &operator++() { pos = pos->next; return *this; } Iterator operator++(int) { auto old = *this; pos = pos->next; return old; } Iterator operator+=(size_t size) { for (size_t i = 0; (i < size) && (pos != nullptr); i++) { pos = &(*pos)->next; } } T *operator->() const { return &pos->value; } T &operator*() const { return pos->value; } bool operator!=(const Iterator &iter) { return pos != iter.pos; } bool operator==(const Iterator &iter) { return pos == iter.pos; } private: Node *pos = nullptr; }; LinkedList() { m_last = reinterpret_cast(&m_header); } LinkedList(std::initializer_list init) { m_last = reinterpret_cast(&m_header); for (auto &value : init) { append(value); } } LinkedList(const LinkedList &other) { auto sourceNode = other.m_header.next; auto targetNode = reinterpret_cast(&m_header); while (sourceNode != nullptr) { auto newNode = create(); if (newNode == nullptr) THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create node ..."); newNode->value = sourceNode->value; targetNode->next = newNode; targetNode = newNode; sourceNode = sourceNode->next; m_size++; targetNode->next = nullptr; m_last = targetNode; } } LinkedList(LinkedList &&other) { m_size = other.m_size; m_header = other.m_header; m_last = other.m_last; other.m_size = 0; other.m_header.next = nullptr; other.m_last = reinterpret_cast(&other.m_header); } ~LinkedList() { clear(); } void swap(LinkedList &other) { if (this == &other) return; auto tempSize = other.m_size; auto tempHeader = other.m_header; auto tempLast = other.m_last; other.m_header = m_header; other.m_size = m_size; other.m_last = m_last; m_header = tempHeader; m_size = tempSize; m_last = tempLast; } virtual void append(const T &value) { auto node = create(); if (node == nullptr) THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create node ..."); node->value = value; node->next = m_last->next; // for circular linked list m_last->next = node; m_last = node; m_size++; } virtual void insert(size_t index, const T &value) { if (index >= m_size) return append(value); Node *prev = position(index); Node *node = create(); if (node == nullptr) THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create node ..."); node->value = value; node->next = prev->next; prev->next = node; m_size += 1; } T &last() override { if (m_size <= 0) THROW_EXCEPTION(InvalidOperationException, "There is no element in the container."); return m_last->value; } void removeAt(size_t index) override { if (index >= m_size) THROW_EXCEPTION(IndexOutOfBoundsException, "The index is out of range."); Node *prev = position(index); Node *toDel = prev->next; prev->next = toDel->next; if (index == m_size - 1) m_last = prev; m_size--; destroy(toDel); } virtual void clear() { while (m_header.next != nullptr) { Node *del = m_header.next; m_header.next = del->next; m_size--; destroy(del); } m_last = reinterpret_cast(&m_header); } virtual size_t size() const noexcept { return m_size; } virtual size_t indexOf(const T &value, size_t from = 0) const final { auto node = position(from)->next; for (size_t i = from; i < m_size; i++, node = node->next) { if (node->value == value) return i; } return LinkedList::npos; } Iterator begin() { return Iterator(m_header.next); } Iterator begin() const { return Iterator(m_header.next); } virtual Iterator end() { return Iterator(); } virtual Iterator end() const { return Iterator(); } T &operator[](size_t index) override { if (index >= m_size) THROW_EXCEPTION(IndexOutOfBoundsException, "Index out of bounds..."); return position(index)->next->value; } protected: Node *position(size_t index) const { Node *ret = reinterpret_cast(&m_header); for (size_t i = 0; i < index; i++) { ret = ret->next; } return ret; } virtual Node *create() { return new Node(); } virtual void destroy(Node *p) { delete p; } size_t m_size = 0; Node *m_last = nullptr; }; } // namespace Kylin #endif // LINKEDLIST_H