// The list data-structure is fundamental and used as building blocks
// for other data-structures. The inheritance and template
// mechanisms in C++ allows for generic list classes with minimum
// duplication of code.
// This technique first defines the simplest list node emptyNode as a
// pointer to the next node.
class emptyNode {
public:
emptyNode *next;
emptyNode () { next = 0; }
emptyNode (emptyNode *p) { next = p; }
};
// With emptyNode, the simplest list is two pointers to the front and
// rear emptyNode instances. In addition, an integer counter len allows
// for the length of the list to be determined efficiently.
class emptyList {
protected:
emptyNode *head, *tail;
int len;
public:
int empty() { return(head == 0); }
int length() { return len; }
void insert(emptyNode *);
void append(emptyNode *);
emptyNode *get();
emptyList() { head = tail = 0; len = 0; }
~emptyList();
friend class emptyListIter;
};
// A list iterator allows items of a list to be traversed conveniently.
// It needs a pointer to a list node to indicate how much of a list has
// been processed.
class emptyListIter {
emptyNode *current;
public:
emptyListIter(emptyList *l) { current = l->head; }
void init(emptyList *l) { current = l->head; }
emptyNode *operator() () {
if (!current) return 0;
emptyNode *p = current;
current = current->next;
return p;
}
};
// With the simplest nodes, lists and iterators, template subclass of
// these may be defined. The classes node and listIter define the nodes
// and iterators for the generic list class by using the template
// mechanism.
// As an example, a list of integers intList may be defined as:
// list<int> intList;
//
// Similarly, an integer list iterator forEachInt is defined as:
// listIter<int> forEach(&intList);
//
// Subsequently, items in that list are processed via:
// int *p;
// while (p = forEach())
// printf("%d\n", *p);
template<class T>
class node : public emptyNode {
public:
T item;
node(const T &i) : item(i) { }
};
template<class T>
class list : public emptyList {
public:
void insert(const T &i)
{ emptyList::insert(new node<T>(i)); }
void append(const T &i)
{ emptyList::append(new node<T>(i)); }
// The get() member function receives the first item in the list. It
// relies on its base class, but also performs housekeeping by deleting
// the unused node.
inline T get();
// The find() member function relies on the iterator to scan the list.
inline T *find(const T &target);
// The remove() member function removes the node that corresponds to the
// target.
inline void remove(const T &target);
// As with the find() member function, contains() and setUnion() relies
// on the iterator to appropriately process items of a list.
inline int contains(list<T> &a);
inline void setUnion(list<T> &a);
};
template<class T>
class listIter : emptyListIter {
public:
listIter(list<T> *s) : emptyListIter(s) { }
void init(list<T> *s) { emptyListIter::init(s); }
T* operator() () {
node<T> *l = (node<T> *) emptyListIter::operator() ();
return(l ? &l->item : 0);
}
};
template <class T>
inline
T list<T>::get()
{
node<T> *p = (node<T> *) emptyList::get();
T i = p->item;
delete p;
return i;
}
// The find() member function relies on the iterator to scan the list.
template <class T>
inline
T *list<T>::find(const T &target)
{
listIter<T> forEach(this);
T *p;
while (p = forEach())
if (*p == target)
return(p);
return 0;
}
// The remove() member function removes the node that corresponds to the
// target.
template <class T>
inline
void list<T>::remove(const T &target)
{
node<T> *p = (node<T> *) head;
node<T> *previous = 0;
while (p) {
if (target == p->item) {
if (tail == p)
tail = previous;
if (previous == 0)
head = p->next;
else
previous->next = p->next;
delete p;
--len;
return;
}
previous = p;
p = (node<T> *) p->next;
}
}
// As with the find() member function, contains() and setUnion() relies
// on the iterator to appropriately process items of a list.
template <class T>
inline
int list<T>::contains(list<T> &a)
{
listIter<T> forEach(&a);
T *p;
while (p = forEach())
if (!find(*p))
return FALSE;
return TRUE;
}
template <class T>
inline
void list<T>::setUnion(list<T> &a)
{
listIter<T> forEach(&a);
T *p;
while (p = forEach())
if (!find(*p))
append(*p);
}
syntax highlighted by Code2HTML, v. 0.9.1