105 lines
4.1 KiB
C
105 lines
4.1 KiB
C
|
#ifndef DOUBLY_LINKED_LIST_H
|
||
|
#define DOUBLY_LINKED_LIST_H
|
||
|
|
||
|
#include <cassert>
|
||
|
#include "sequence.h"
|
||
|
|
||
|
namespace seq
|
||
|
{
|
||
|
class DoublyLinkedListNode
|
||
|
{
|
||
|
public:
|
||
|
// return a reference to the stored item
|
||
|
int& get_item() { return this->item; }
|
||
|
|
||
|
// return pointer to next node, or nullptr if this is the final node
|
||
|
DoublyLinkedListNode* get_next() const { return this->next; }
|
||
|
|
||
|
// return pointer to previous node, or nullptr if this is the initial node
|
||
|
DoublyLinkedListNode* get_prev() const { return this->prev; }
|
||
|
|
||
|
// overwrite the item stored in this node
|
||
|
void set_item(int in_item) { this->item = in_item; }
|
||
|
|
||
|
private:
|
||
|
int item = 0;
|
||
|
DoublyLinkedListNode* next = nullptr;
|
||
|
DoublyLinkedListNode* prev = nullptr;
|
||
|
|
||
|
// attach a node behind this node
|
||
|
// if there was a node attached to this previously, it is NOT deleted!
|
||
|
void set_next(DoublyLinkedListNode* in_next) { this->next = in_next; }
|
||
|
|
||
|
// attach a node before this node
|
||
|
// if there was a node attached to this previously, it is NOT deleted!
|
||
|
void set_prev(DoublyLinkedListNode* in_prev) { this->prev = in_prev; }
|
||
|
|
||
|
friend class DoublyLinkedList; // allow DoublyLinkedList to access private members
|
||
|
};
|
||
|
|
||
|
class DoublyLinkedList: public Sequence
|
||
|
{
|
||
|
public:
|
||
|
bool empty() const { return (this->head == nullptr); } // test whether the doubly linked list is empty
|
||
|
size_t size() const; // return the size (number of items in the doubly linked list)
|
||
|
|
||
|
// it is the caller's responsibility to ensure that the list is not empty when calling front() or back()!
|
||
|
int& front() { assert(this->head); return this->head->get_item(); } // return a reference to the first item
|
||
|
int& back() { assert(this->tail); return this->tail->get_item(); } // return a reference to the final item
|
||
|
|
||
|
// return a reference to the item at position i of the list, counting from 0
|
||
|
// for negative numbers, count from the tail (-1) backward (-2, -3, ...)
|
||
|
// it is the caller's responsibility that the index is within range
|
||
|
int& at(int i) { return this->index(i)->get_item(); }
|
||
|
|
||
|
// return pointer to the head/tail node
|
||
|
DoublyLinkedListNode* begin() const { return this->head; }
|
||
|
DoublyLinkedListNode* end() const { return this->tail; }
|
||
|
|
||
|
// return pointer to the node at position i, counting from 0
|
||
|
// for negative numbers, count from the tail (-1) backward (-2, -3, ...)
|
||
|
DoublyLinkedListNode* index(int i) const;
|
||
|
|
||
|
/*
|
||
|
* accepts an additional item into the doubly linked list;
|
||
|
* by default, this is done at the back end of the list
|
||
|
* call push_front(...) to push an element at the front
|
||
|
*
|
||
|
* the list takes ownership of the copy (but not of the original!)
|
||
|
*/
|
||
|
void push(const int& pushed_item) { this->push_back(pushed_item); }
|
||
|
void push_back(const int& pushed_item);
|
||
|
void push_front(const int& pushed_item);
|
||
|
|
||
|
/*
|
||
|
* removes an item from the list (front end by default)
|
||
|
* to do the same at the back, call pop_back()
|
||
|
*/
|
||
|
void pop() { this->pop_front(); }
|
||
|
void pop_front();
|
||
|
void pop_back();
|
||
|
void clear() { while(!this->empty()) this->pop(); } // remove all the items from the list
|
||
|
|
||
|
// it is the caller's responsibility that the index is within range
|
||
|
// for negative numbers, count from the tail (-1) backward (-2, -3, ...)
|
||
|
void insert_at(int i, const int& inserted_item); // insert an item at index i
|
||
|
void erase_at(int i); // remove the item at index i
|
||
|
|
||
|
// it is the caller's responsibility that the node is actually part of the list
|
||
|
void insert_successor_to(DoublyLinkedListNode* predecessor, const int& inserted_item); // insert an item after given node
|
||
|
void erase_successor_to(DoublyLinkedListNode* predecessor) // remove the item after given node
|
||
|
{
|
||
|
this->erase_node(predecessor->get_next());
|
||
|
}
|
||
|
void erase_node(DoublyLinkedListNode* erased_node);
|
||
|
|
||
|
~DoublyLinkedList() { this->clear(); }
|
||
|
|
||
|
private:
|
||
|
DoublyLinkedListNode* head = nullptr;
|
||
|
DoublyLinkedListNode* tail = nullptr;
|
||
|
};
|
||
|
}
|
||
|
|
||
|
#endif
|