159 lines
3.3 KiB
C++

#pragma once
#include <cassert>
template <typename DataType>
class LinkedList {
struct Node {
DataType data;
Node* next;
Node* previous;
Node(DataType data, Node* next, Node* previous):
data(data),
next(next),
previous(previous)
{}
};
int count = 0;
Node* head = nullptr;
Node* tail = nullptr;
public:
class Iterator {
Node *node = nullptr;
public:
Iterator(Node* node)
: node(node) {}
bool advance(size_t n) {
size_t i = 0;
if (n == 0) {
return true;
}
for (; node && (i < n); ++i) {
node = node->next;
}
return (i > 0);
}
DataType& operator* ()
{
return node->data;
}
DataType* operator-> ()
{
return &(node->data);
}
Iterator operator++ (int) {
assert(advance(1));
Iterator i(node);
return i;
}
bool operator==(const Iterator& right) const {
return node == right.node;
}
bool operator!=(const Iterator& right) const {
return node != right.node;
}
};
void pushFront(DataType data) {
auto* new_node = new Node(data, head, nullptr);
if (head != nullptr) {
head->previous = new_node;
}
if (tail == nullptr) {
tail = new_node;
}
head = new_node;
count++;
}
void pushBack(DataType data) {
auto* new_node = new Node(data, nullptr, tail);
if (head == nullptr) {
head = new_node;
}
if (tail != nullptr) {
tail->next = new_node;
}
tail = new_node;
count++;
}
void popFront() {
if (head != nullptr) {
bool is_last_node = (head == tail);
Node* node_to_delete = head;
head = node_to_delete->next;
if (is_last_node) {
tail = nullptr;
}
delete node_to_delete;
count--;
}
}
void popBack() {
if (tail != nullptr) {
bool is_last_node = (head == tail);
Node* node_to_delete = tail;
tail = node_to_delete->previous;
if (is_last_node) {
head = nullptr;
}
delete node_to_delete;
count--;
}
}
DataType back() const {
assert(tail != nullptr);
return tail->data;
}
DataType front() const {
assert(head != nullptr);
return head->data;
}
Iterator begin() const {
return Iterator(head);
}
Iterator end() const {
return Iterator(nullptr);
}
bool empty() const {
return head == nullptr;
}
int size() const { return count; }
DataType operator [] (int i) const {
auto iter = begin();
assert(iter.advance(i));
return *iter;
}
DataType& operator [] (int i) {
auto iter = begin();
assert(iter.advance(i));
return *iter;
}
};