Kylin/DataStructure/CircularLinkedList.h
2023-12-27 10:29:16 +08:00

110 lines
3.6 KiB
C++

#ifndef CIRCULARLIST_H
#define CIRCULARLIST_H
#include "LinkedList.h"
namespace Kylin {
template <typename T>
class CircularLinkedList : public LinkedList<T> {
using Node = typename LinkedList<T>::Node;
using Iterator = typename LinkedList<T>::Iterator;
public:
CircularLinkedList() = default;
CircularLinkedList(std::initializer_list<T> init) {
this->m_header.next = reinterpret_cast<Node *>(&this->m_header);
this->m_last = reinterpret_cast<Node *>(&this->m_header);
for (auto &value : init) {
this->append(value);
}
}
CircularLinkedList(const CircularLinkedList &other) {
this->m_header.next = 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;
targetNode->next = newNode;
targetNode = newNode;
sourceNode = sourceNode->next;
this->m_size++;
targetNode->next = this->m_header.next;
this->m_last = targetNode;
}
}
CircularLinkedList(CircularLinkedList &&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 this->append(value);
LinkedList<T>::insert(index, value);
if (index == 0) lastToFirst();
}
void removeAt(size_t index) override {
if (this->size() <= 0)
THROW_EXCEPTION(IndexOutOfBoundsException, "There is no element in the container.");
index = mod(index);
if (index == 0) {
auto toDel = this->m_header.next;
this->m_header.next = toDel->next;
this->m_size--;
if (this->m_size == 0) {
this->m_header.next = nullptr;
} else {
lastToFirst();
}
this->destroy(toDel);
} else {
LinkedList<T>::removeAt(index);
}
}
virtual void clear() {
while (this->m_size > 1) {
removeAt(1);
}
if (this->m_size == 1) {
auto del = this->m_header.next;
this->m_header.next = nullptr;
this->m_size = 0;
this->destroy(del);
}
}
Iterator end() override { return Iterator(reinterpret_cast<Node *>(&this->m_header)); }
Iterator end() const override { return Iterator(reinterpret_cast<Node *>(&this->m_header)); }
T &operator[](size_t index) override {
if (this->m_size <= 0)
THROW_EXCEPTION(InvalidOperationException, "There is no element in the container...");
index = mod(index);
return this->position(index)->next->value;
}
virtual ~CircularLinkedList() { clear(); }
protected:
size_t mod(size_t index) const { return (this->m_size == 0) ? 0 : (index % this->m_size); }
void lastToFirst() { this->position(this->m_size - 1)->next->next = this->m_header.next; }
};
} // namespace Kylin
#endif // CIRCULARLIST_H