Skip to content

Instantly share code, notes, and snippets.

@dgodfrey206
Created December 12, 2014 03:15
Show Gist options
  • Save dgodfrey206/869e029f5b2ceedd168e to your computer and use it in GitHub Desktop.
Save dgodfrey206/869e029f5b2ceedd168e to your computer and use it in GitHub Desktop.
Doubly linked list
#include <iostream>
#include <initializer_list>
#include <stdexcept>
template <class T>
class list;
template <class T>
class Node
{
Node(T const& data, Node* next = nullptr, Node* prev = nullptr)
: data(data)
, next(next)
, prev(prev)
{ }
friend class list<T>;
private:
T data{0};
Node* next{0}, *prev{0};
};
template <class T>
class list
{
typedef T& reference;
typedef T const& const_reference;
typedef unsigned int size_type;
template <class U>
using ref_ptr = U*&;
public:
list();
list(std::initializer_list<T>);
list(list const&);
list& operator=(list const&);
void assign(list const&);
reference operator[](size_type);
const_reference operator[](size_type) const;
reference front();
const_reference front() const;
reference back();
const_reference back() const;
bool empty() const;
size_type size() const;
size_type max_size() const;
void push_back(T const&);
void pop_back();
void push_front(T const&);
void pop_front();
void clear();
void swap(list<T>&);
private:
Node<T>* head;
Node<T>* tail;
mutable size_type m_size{0};
private:
void delete_node(Node<T>**);
void internal_swap(ref_ptr<Node<T>>, ref_ptr<Node<T>>);
void dec_size() const { if (m_size) --m_size; }
void inc_size() const { ++m_size; }
};
template <class T>
list<T>::list()
: head{0}, tail{0}
{ }
template <class T>
list<T>::list(std::initializer_list<T> l)
: head{0}
, tail{0}
{
for (auto const& x : l)
push_back(x);
}
template <class T>
list<T>::list(list<T> const& other) { assign(other); }
template <class T>
void list<T>::push_back(T const& value)
{
Node<T>* node = new Node<T>{value};
if (head == nullptr)
head = node;
else
tail->next = node;
tail = node;
inc_size();
}
template <class T>
void list<T>::push_front(T const& value)
{
head = new Node<T>{value, head};
inc_size();
}
template <class T>
void list<T>::pop_front()
{
Node<T>* temp = head;
head = head->next;
delete temp;
dec_size();
}
template <class T>
void list<T>::pop_back()
{
Node<T>* oldTail = tail;
tail = tail->prev;
delete oldTail;
dec_size();
}
template <class T>
void list<T>::assign(list<T> const& other)
{
head = 0;
tail = 0;
for (auto first = other.head; first != nullptr; first = first->next)
push_back(first->data);
}
template <class T>
auto list<T>::operator[](size_type pos) -> reference
{
if (pos >= m_size)
throw std::out_of_range("Position out of range.");
Node<T>* ptr = head;
size_type count = 0;
while (ptr && count != pos)
{
ptr = ptr->next;
count++;
}
return ptr->data;
}
template <class T>
auto list<T>::operator[](size_type pos) const -> const_reference
{
return const_cast<list<T>&>(*this)[pos];
}
template <class T>
list<T>& list<T>::operator=(list<T> const& other)
{
assign(other);
return *this;
}
template <class T> auto list<T>::front() -> reference { return head->data; }
template <class T> auto list<T>::front() const -> const_reference { return head->data; }
template <class T> auto list<T>::back() -> reference { return tail->data; }
template <class T> auto list<T>::back() const -> const_reference { return tail->data; }
template <class T>
bool list<T>::empty() const { return head != nullptr; }
template <class T>
auto list<T>::size() const -> size_type
{ return m_size; }
template <class T>
void list<T>::clear()
{
for (; head != nullptr; head = head->next)
delete_node(&head);
}
template <class T>
void list<T>::swap(list<T>& other)
{
internal_swap(head, other.head);
std::swap(m_size, other.m_size);
}
template <class T>
void list<T>::internal_swap(ref_ptr<Node<T>> lhs, ref_ptr<Node<T>> rhs)
{
using std::swap;
swap(lhs, rhs);
Node<T> **lnext = &lhs, **rnext = &rhs;
if (lhs) lnext = &lhs->next;
if (rhs) rnext = &rhs->next;
if (*lnext || *rnext)
internal_swap(*lnext, *rnext);
}
template <class T>
void list<T>::delete_node(Node<T>** node)
{
Node<T> **prev = &(*node)->prev, **next = &(*node)->next;
delete *node;
*prev = *next;
dec_size();
}
int main()
{
list<int> l{1, 2, 3, 4};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment