Files
pl/include/prelude/linkedlist.hpp

97 lines
2.1 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:
View<T> ToView()
{
Builder<T> b;
for(ListNode<T>* cur = Begin(); cur != nullptr; cur = cur->next)
{
b.Push(cur->value);
}
return b.view();
}
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;
};