From 298160f0154a05030681a208a247e2ed309f89db Mon Sep 17 00:00:00 2001 From: JP Cimalando Date: Sat, 10 Nov 2018 16:59:35 +0100 Subject: linked list structure + users --- src/structures/pl_list.hpp | 128 ++++++++++++++++++ src/structures/pl_list.tcc | 329 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 457 insertions(+) create mode 100644 src/structures/pl_list.hpp create mode 100644 src/structures/pl_list.tcc (limited to 'src/structures') diff --git a/src/structures/pl_list.hpp b/src/structures/pl_list.hpp new file mode 100644 index 0000000..327e259 --- /dev/null +++ b/src/structures/pl_list.hpp @@ -0,0 +1,128 @@ +// Copyright Jean Pierre Cimalando 2018. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef PL_LIST_HPP +#define PL_LIST_HPP + +#include +#include + +/* + pl_cell: the linked list cell + */ +template +struct pl_cell; + +template +struct pl_basic_cell +{ + pl_cell *prev, *next; +}; + +template +struct pl_cell : pl_basic_cell +{ + T value; +}; + +/* + pl_iterator: the linked list iterator + */ +template +class pl_iterator +{ +public: + typedef std::bidirectional_iterator_tag iterator_category; + typedef Cell value_type; + typedef Cell &reference; + typedef Cell *pointer; + typedef std::ptrdiff_t difference_type; + + pl_iterator(Cell *cell = NULL); + bool is_end() const; + Cell &operator*() const; + Cell *operator->() const; + bool operator==(const pl_iterator &i) const; + bool operator!=(const pl_iterator &i) const; + pl_iterator &operator++(); + pl_iterator operator++(int); + pl_iterator &operator--(); + pl_iterator operator--(int); + +private: + Cell *cell_; +}; + +/* + pl_list: the preallocated linked list + */ +template +class pl_list +{ +public: + typedef pl_cell value_type; + typedef value_type *pointer; + typedef value_type &reference; + typedef const value_type *const_pointer; + typedef const value_type &const_reference; + typedef pl_iterator< pl_cell > iterator; + typedef pl_iterator< const pl_cell > const_iterator; + + pl_list(std::size_t capacity = 0); + ~pl_list(); + + pl_list(const pl_list &other); + pl_list &operator=(const pl_list &other); + + std::size_t size() const; + std::size_t capacity() const; + bool empty() const; + + iterator begin(); + iterator end(); + const_iterator begin() const; + const_iterator end() const; + + void clear(); + + pl_cell &front(); + const pl_cell &front() const; + pl_cell &back(); + const pl_cell &back() const; + + iterator insert(iterator pos, const T &x); + iterator erase(iterator pos); + void push_front(const T &x); + void push_back(const T &x); + void pop_front(); + void pop_back(); + + iterator find(const T &x); + const_iterator find(const T &x) const; + template iterator find_if(const Pred &p); + template const_iterator find_if(const Pred &p) const; + +private: + // number of cells in the list + std::size_t size_; + // number of cells allocated + std::size_t capacity_; + // array of cells allocated + pl_cell *cells_; + // pointer to the head cell + pl_cell *first_; + // pointer to the next free cell + pl_cell *free_; + // value-less cell which terminates the linked list + pl_basic_cell endcell_; + + void initialize(std::size_t capacity); + pl_cell *allocate(pl_cell *pos); + void deallocate(pl_cell *cell); +}; + +#include "pl_list.tcc" + +#endif // PL_LIST_HPP diff --git a/src/structures/pl_list.tcc b/src/structures/pl_list.tcc new file mode 100644 index 0000000..37ccc75 --- /dev/null +++ b/src/structures/pl_list.tcc @@ -0,0 +1,329 @@ +// Copyright Jean Pierre Cimalando 2018. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include "pl_list.hpp" + +template +pl_iterator::pl_iterator(Cell *cell) + : cell_(cell) +{ +} + +template +bool pl_iterator::is_end() const +{ + return cell_->next == NULL; +} + +template +Cell &pl_iterator::operator*() const +{ + return *cell_; +} + +template +Cell *pl_iterator::operator->() const +{ + return cell_; +} + +template +bool pl_iterator::operator==(const pl_iterator &i) const +{ + return cell_ == i.cell_; +} + +template +bool pl_iterator::operator!=(const pl_iterator &i) const +{ + return cell_ != i.cell_; +} + +template +pl_iterator &pl_iterator::operator++() +{ + cell_ = cell_->next; + return *this; +} + +template +pl_iterator pl_iterator::operator++(int) +{ + pl_iterator i(cell_); + cell_ = cell_->next; + return i; +} + +template +pl_iterator &pl_iterator::operator--() +{ + cell_ = cell_->prev; + return *this; +} + +template +pl_iterator pl_iterator::operator--(int) +{ + pl_iterator i(cell_); + cell_ = cell_->prev; + return i; +} + +template +pl_list::pl_list(std::size_t capacity) +{ + initialize(capacity); +} + +template +pl_list::~pl_list() +{ + delete[] cells_; +} + +template +pl_list::pl_list(const pl_list &other) +{ + initialize(other.capacity()); + for(const_iterator i = other.end(), b = other.begin(); i-- != b;) + push_front(i->value); +} + +template +pl_list &pl_list::operator=(const pl_list &other) +{ + if(this != &other) + { + std::size_t size = other.size(); + if(size <= capacity()) + clear(); + else + { + pl_cell *oldcells = cells_; + initialize(other.capacity()); + delete[] oldcells; + } + for(const_iterator i = other.end(), b = other.begin(); i-- != b;) + push_front(i->value); + } + return *this; +} + +template +std::size_t pl_list::size() const +{ + return size_; +} + +template +std::size_t pl_list::capacity() const +{ + return capacity_; +} + +template +bool pl_list::empty() const +{ + return size_ == 0; +} + +template +typename pl_list::iterator pl_list::begin() +{ + return iterator(first_); +} + +template +typename pl_list::iterator pl_list::end() +{ + return iterator(reinterpret_cast *>(&endcell_)); +} + +template +typename pl_list::const_iterator pl_list::begin() const +{ + return const_iterator(first_); +} + +template +typename pl_list::const_iterator pl_list::end() const +{ + return const_iterator(reinterpret_cast *>(&endcell_)); +} + +template +void pl_list::clear() +{ + std::size_t capacity = capacity_; + pl_cell *cells = cells_; + pl_cell *endcell = &*end(); + size_ = 0; + first_ = endcell; + free_ = cells; + endcell->prev = NULL; + for(std::size_t i = 0; i < capacity; ++i) + { + cells[i].prev = (i > 0) ? &cells[i - 1] : NULL; + cells[i].next = (i + 1 < capacity) ? &cells[i + 1] : NULL; + cells[i].value = T(); + } +} + +template +pl_cell &pl_list::front() +{ + return *first_; +} + +template +const pl_cell &pl_list::front() const +{ + return *first_; +} + +template +pl_cell &pl_list::back() +{ + iterator i = end(); + return *--i; +} + +template +const pl_cell &pl_list::back() const +{ + const_iterator i = end(); + return *--i; +} + +template +typename pl_list::iterator pl_list::insert(iterator pos, const T &x) +{ + pl_cell *cell = allocate(&*pos); + if (!cell) + throw std::bad_alloc(); + cell->value = x; + return iterator(cell); +} + +template +typename pl_list::iterator pl_list::erase(iterator pos) +{ + deallocate(&*(pos++)); + return pos; +} + +template +void pl_list::push_front(const T &x) +{ + insert(begin(), x); +} + +template +void pl_list::push_back(const T &x) +{ + insert(end(), x); +} + +template +void pl_list::pop_front() +{ + deallocate(first_); +} + +template +void pl_list::pop_back() +{ + iterator i(&*end()); + deallocate(&*--i); +} + +template +typename pl_list::iterator pl_list::find(const T &x) +{ + const_iterator i = const_cast *>(this)->find(x); + return iterator(&const_cast(*i)); +} + +template +typename pl_list::const_iterator pl_list::find(const T &x) const +{ + const_iterator e = end(); + for (const_iterator i = begin(); i != e; ++i) + { + if(i->value == x) + return i; + } + return e; +} + +template +template +typename pl_list::iterator pl_list::find_if(const Pred &p) +{ + const_iterator i = const_cast *>(this)->find_if(p); + return iterator(&const_cast(*i)); +} + +template +template +typename pl_list::const_iterator pl_list::find_if(const Pred &p) const +{ + const_iterator e = end(); + for (const_iterator i = begin(); i != e; ++i) + { + if(p(i->value)) + return i; + } + return e; +} + +template +void pl_list::initialize(std::size_t capacity) +{ + cells_ = new pl_cell[capacity]; + capacity_ = capacity; + endcell_.next = NULL; + clear(); +} + +template +pl_cell *pl_list::allocate(pl_cell *pos) +{ + // remove free cells front + pl_cell *cell = free_; + if(!cell) + return NULL; + free_ = cell->next; + if(free_) + free_->prev = NULL; + + // insert at position + if (pos == first_) + first_ = cell; + cell->prev = pos->prev; + if (cell->prev) + cell->prev->next = cell; + cell->next = pos; + pos->prev = cell; + + ++size_; + return cell; +} + +template +void pl_list::deallocate(pl_cell *cell) +{ + if(cell->prev) + cell->prev->next = cell->next; + if(cell->next) + cell->next->prev = cell->prev; + if(cell == first_) + first_ = cell->next; + cell->prev = NULL; + cell->next = free_; + cell->value = T(); + free_ = cell; + --size_; +} -- cgit v1.2.3