159 lines
3.3 KiB
C++
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;
|
|
}
|
|
};
|