Download: tag.zip
Before STL we had to write our own versions of linked-lists. This is mine.
See:
A small test program is contained within the definition file (tag.cpp).
tag.h/* tag.h
*
* tags are used to maintain double-linked lists
*
*/
#if !defined(__TAG_H)
#define __TAG_H
class List;
class Node {
public:
Node *next;
Node *prev;
Node(): next(0), prev(0) { }
virtual ~Node() { }
virtual void show() { }
virtual long size() { return sizeof( Node); }
friend List;
};
class List {
Node *top;
Node *bottom;
int length;
public:
List(): top(0), bottom(0), length(0) { }
~List() { clear(); }
Node *first() { return top; }
Node *last() { return bottom; }
int count() const { return length; }
void append(Node *np);
void prepend(Node *np);
void clear();
int index(Node *np);
void insert(Node *np, int n);
void after(Node *np, Node *after);
int extract(Node *np);
void remove(Node *np);
void show();
long size();
Node *operator [](int n);
};
#endif
tag.cpp/*** tag.cpp $Revision: 1.1 $ $Date: 23 Jan 1991 21:10:20 $
*
* Maintain double-linked lists
*
***/
#include "stdio.h"
#include <string>
#include "tag.h"
using namespace std;
#if defined(TAG_TEST)
class Label: public Node {
public:
string item;
Label(char *name) { item = name; }
~Label() { printf("Deleting node: %s\n",item.c_str()); }
void show();
};
List labels;
#define MAXC 128
char text[MAXC];
void print(const char *text);
void show_list(List &lp);
void main()
{
int i,ntag=0;
Node *np;
for (i=0; i<6; i++) {
sprintf_s(text,MAXC-1,"tag %d",++ntag);
np = new Label(text);
labels.append(np);
}
show_list(labels);
np = labels[5];
printf("testing index function (offset 5): %d\n",labels.index(np));
if (np) {
print("\nnode at position 5 is ");
np->show();
print("\n\n");
}
ntag = 3;
printf("\n Remove node %d\n\n",ntag);
labels.remove(labels[ntag-1]);
show_list(labels);
}
void print(const char *text)
{
fputs(text,stdout);
}
void Label::show()
{
sprintf_s(text,MAXC-1,"%8x %8x %8x ",this,next,prev);
print(text);
print(item.c_str());
print("\n");
}
void show_list(List &lp)
{
sprintf_s(text,MAXC-1,"\n%8s %8s %8s %8s\n","list","first","last","length");
print(text);
sprintf_s(text,MAXC-1,"%8x %8x %8x ",&lp,lp.first(),lp.last());
print(text);
sprintf_s(text,MAXC-1,"%8d\n\n",lp.count());
print(text);
sprintf_s(text,MAXC-1,"%8s %8s %8s\n","node","next","prev");
print(text);
lp.show();
print("\n\n");
}
#endif
void List::show()
{
Node *np;
for (np=first(); np; np=np->next) np->show();
}
long List::size()
{
Node *np;
long sum = sizeof(List);
for (np=first(); np; np=np->next) sum += np->size();
return sum;
}
/* remove
*
* Cut specified node from list and return it
* to the list of available nodes.
*
*/
void List::remove(Node *np)
{
if (extract(np)) delete np;
}
/*
*
* Clear all nodes from list
*
*/
void List::clear()
{
while (length) remove(top);
}
/* append
*
* Add node to bottom of list
*
*/
void List::append(Node *np)
{
Node *c;
if (!np) return;
c = bottom;
np->next = 0;
np->prev = c;
bottom = np;
if (c) c->next = np;
else top = np;
length++;
}
/* prepend
*
* Add node to top of list
*
*/
void List::prepend(Node *np)
{
Node *c;
if (!np) return;
c = top;
np->prev = 0;
np->next = c;
top = np;
if (c) c->prev = np;
else bottom = np;
length++;
}
// Extract specified node from list
int List::extract(Node *np)
{
Node *next, *prev;
int n = index(np);
if (!n) return 0;
next = np->next;
prev = np->prev;
if (prev) prev->next = next;
else top = next;
if (next) next->prev = prev;
else bottom = prev;
np->next = np->prev = 0;
length--;
return 1;
}
// returns position if node is in list and 0 otherwise.
int List::index(Node *np)
{
Node *tp;
int position;
position = 0;
for (tp=top; tp; tp=tp->next) {
position++;
if (tp==np) return position;
}
return 0;
}
// returns node from specified offset (index-1) in list
Node *List::operator [](int n)
{
int i;
Node *np;
if (n<0) return 0;
np = top;
for (i=0; i<n; i++) {
if (np) np = np->next;
else break;
}
return np;
}
// add node after specified position in list
void List::insert(Node *np, int n)
{
Node *cur, *pre;
if (!np) return;
cur = (*this)[n];
if (cur) {
pre = cur->prev;
if (pre) {
np->prev = cur->prev;
np->next = cur;
pre->next = np;
cur->prev = np;
length++;
}
else prepend(np);
}
else append(np);
}
// add node after specified node (which should be in the list)
void List::after(Node *np, Node *aft)
{
Node *post;
if (!aft) prepend(np);
else if (index(aft) > 0) {
post = aft->next;
aft->next = np;
np->prev = aft;
np->next = post;
post->prev = np;
length++;
}
}
list first last length
411100 323f18 322dc0 6
node next prev
323f18 323f48 0 tag 1
323f48 323f78 323f18 tag 2
323f78 323fa8 323f48 tag 3
323fa8 323fd8 323f78 tag 4
323fd8 322dc0 323fa8 tag 5
322dc0 0 323fd8 tag 6
testing index function (offset 5): 6
node at position 5 is 322dc0 0 323fd8 tag 6
Remove node 3
Deleting node: tag 3
list first last length
411100 323f18 322dc0 5
node next prev
323f18 323f48 0 tag 1
323f48 323fa8 323f18 tag 2
323fa8 323fd8 323f48 tag 4
323fd8 322dc0 323fa8 tag 5
322dc0 0 323fd8 tag 6
Deleting node: tag 1
Deleting node: tag 2
Deleting node: tag 4
Deleting node: tag 5
Deleting node: tag 6
Maintained by John Loomis, updated Tue Feb 13 00:30:28 2007