86 lines
1.9 KiB
C++
86 lines
1.9 KiB
C++
#pragma once
|
|
#include <cstddef>
|
|
#include "prelude/string.hpp"
|
|
|
|
template<typename T>
|
|
struct ListNode
|
|
{
|
|
T value;
|
|
ListNode* prev = nullptr;
|
|
ListNode* next = nullptr;
|
|
};
|
|
|
|
template<typename T>
|
|
class DoubleLinkedList {
|
|
public:
|
|
DoubleLinkedList() = default;
|
|
|
|
public:
|
|
static DoubleLinkedList<T> FromView(const View<T> &view)
|
|
{
|
|
auto list = DoubleLinkedList<T>();
|
|
for (size_t i = 0; i < view.size; ++i)
|
|
{
|
|
list.Append(new ListNode<T>(view.data[i]));
|
|
}
|
|
return list;
|
|
}
|
|
|
|
public:
|
|
void Append(ListNode<T>* node)
|
|
{
|
|
if (IsEmpty())
|
|
{
|
|
node->next = nullptr;
|
|
node->prev = nullptr;
|
|
tail = node;
|
|
head = node;
|
|
} else {
|
|
head->next = node;
|
|
node->prev = head;
|
|
node->next = nullptr;
|
|
head = node;
|
|
}
|
|
m_size++;
|
|
}
|
|
|
|
void Prepend(ListNode<T>* node)
|
|
{
|
|
if (IsEmpty())
|
|
{
|
|
Append(node);
|
|
} else {
|
|
tail->prev = node;
|
|
node->next = tail;
|
|
node->prev = nullptr;
|
|
tail = node;
|
|
m_size++;
|
|
}
|
|
}
|
|
|
|
void SpliceFront(ListNode<T>* node)
|
|
{
|
|
if (m_size == 1 && tail == node && head == node) return;
|
|
assert((node->next || node->prev) && "node should be inside of the linked list");
|
|
if (node == tail) return;
|
|
if (node == head) {
|
|
node->prev->next = nullptr;
|
|
head = node->prev;
|
|
} else {
|
|
node->prev->next = node->next;
|
|
node->next->prev = node->prev;
|
|
}
|
|
m_size--;
|
|
Prepend(node);
|
|
}
|
|
|
|
bool IsEmpty() const { return m_size == 0; }
|
|
|
|
ListNode<T>* Begin() const { return tail; }
|
|
ListNode<T>* End() const { return head; }
|
|
private:
|
|
ListNode<T>* head = nullptr;
|
|
ListNode<T>* tail = nullptr;
|
|
size_t m_size = 0;
|
|
};
|