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