#ifndef DLLISTUTILS_H
#define DLLISTUTILS_H
#include <cstdlib> // for NULL
/**
* Utility operations for doubly linked lists
*
* Variant: header has first and last pointers
*
*/
template <typename Data>
struct DListNode
{
Data data;
DListNode<Data>* prev;
DListNode<Data>* next;
DListNode() {next = prev = 0;}
DListNode (const Data& d, DListNode<Data>* prv = 0, DListNode<Data>* nxt = 0)
: data(d), next(nxt), prev(prv)
{}
};
template <typename Data>
struct DListHeader {
DListNode<Data>* first;
DListNode<Data>* last;
DListHeader();
void addToFront (const Data& value);
void addToEnd (const Data& value);
void addAfter (DListNode<Data>* afterThis, const Data& value);
void addBefore (DListNode<Data>* beforeThis, const Data& value);
void addInOrder (const Data& value);
void remove (DListNode<Data>* here);
void removeAfter (DListNode<Data>* afterThis);
DListNode<Data>* find (const Data& value) const;
DListNode<Data>* findOrdered (const Data& value) const;
void clear();
};
template <typename Data>
DListHeader<Data>::DListHeader()
: first(NULL), last(NULL)
{}
template <typename Data>
void DListHeader<Data>::addToFront (const Data& value)
{
DListNode<Data>* newNode = new DListNode<Data>(value, NULL, first);
if (first == NULL)
first = last = newNode;
else
{
first->prev = newNode;
first = newNode;
}
}
template <typename Data>
void DListHeader<Data>::addToEnd (const Data& value)
{
DListNode<Data>* newNode = new DListNode<Data>(value, last, NULL);
if (last == NULL)
{
first = last = newNode;
}
else
{
last->next = newNode;
last = newNode;
}
}
template <typename Data>
void DListHeader<Data>::addAfter (DListNode<Data>* afterThis,
const Data& value)
{
DListNode<Data>* newNode
= new DListNode<Data>(value, afterThis, afterThis->next);
if (afterThis == last)
{
last = newNode;
}
else
{
afterThis->next->prev = newNode;
afterThis->next = newNode;
}
}
template <typename Data>
void DListHeader<Data>::addBefore (DListNode<Data>* beforeThis,
const Data& value)
{
if (beforeThis == first)
addToFront (value);
else
{
DListNode<Data>* current = beforeThis->prev;
addAfter (current, value);
}
}
template <typename Data>
void DListHeader<Data>::addInOrder (const Data& value)
{
if (first == NULL)
first = last = new DListNode<Data>(value, NULL, NULL);
else
{
DListNode<Data>* current = first;
DListNode<Data>* prev = NULL;
while (current != NULL && value < current->data)
{
prev = current;
current = current->next;
}
if (prev == NULL)
addToFront (value);
else
addAfter (prev, value);
}
}
template <typename Data>
void DListHeader<Data>::remove (DListNode<Data>* here)
{
if (here == first)
{
DListNode<Data>* after = first->next;
delete first;
first = after;
}
else
{
DListNode<Data>* prev = here->prev;
prev->next = here->next;
here->prev = prev;
if (here == last)
last = prev;
delete here;
}
}
template <typename Data>
void DListHeader<Data>::removeAfter (DListNode<Data>* afterThis)
{
DListNode<Data>* toRemove = afterThis->next;
afterThis->next = toRemove->next;
if (afterThis->next != NULL)
afterThis->next->prev = afterThis;
if (toRemove == last)
last = afterThis;
delete toRemove;
}
template <typename Data>
DListNode<Data>* DListHeader<Data>::find (const Data& value) const
{
DListNode<Data>* current = first;
while (current != NULL && value != current->data)
current = current->next;
return current;
}
template <typename Data>
DListNode<Data>* DListHeader<Data>::findOrdered (const Data& value) const
{
DListNode<Data>* current = first;
while (current != NULL && value < current->data)
current = current->next;
if (current != NULL && value == current->data)
return current;
else
return NULL;
}
template <typename Data>
void DListHeader<Data>::clear()
{
DListNode<Data>* current = first;
DListNode<Data>* nxt = NULL;
while (current != NULL)
{
nxt = current->next;
delete current;
current = nxt;
}
first = last = NULL;
}
#endif