# This is a shell archive. Save it in a file, remove anything before # this line, and then unpack it by entering "sh file". Note, it may # create directories; files and directories will be owned by you and # have default permissions. # # This archive contains: # # Makefile # ReadMe # bitvec.h # cstring.h # hash.h # iterator.h # labeledVertex.h # list.h # oldassert.h # openHashTable.h # priorque.h # queue.h # random.h # rational.h # rstream.h # set.h # sim.h # split.h # stack.h # table.h # tree.h # vector.h # vertex.h # bitvec.C # random.C # rational.C # split.C # string.C # hash.c # list.c # openHashTable.c # priorque.c # rstream.c # tree.c # vector.c # vertex.c # echo x - Makefile sed 's/^X//' >Makefile << 'END-of-Makefile' X# X# Makefile X# This makefile compiles the code for the data structures X# directory for Classic Data Structures in C++, X# by Timothy A. Budd. The user must select the X# appropriate macros, depending on the compiler used. X# ILIB is the directory where the include files will be found X# X X# Common Macros XILIB = . X X# Unix Macros XCC = g++ XCFLAGS = -I $(ILIB) XOBJ = .o XEXE = XRM = rm -fr X X# Borland C++ Macros X#CC = bcc X#CFLAGS = -I$(ILIB) -P -N -D__GNUG__ X#OBJ = .obj X#EXE = .exe X#RM = del X Xall: random$(OBJ) string$(OBJ) bitvec$(OBJ) split$(OBJ) X Xbundle: clean X shar Makefile ReadMe *.h *.C *.c >/tmp/ds X Xclean: X $(RM) *$(OBJ) X $(RM) ptrepository X Xrandom$(OBJ): random.C X $(CC) $(CFLAGS) -c random.C X Xstring$(OBJ): string.C X $(CC) $(CFLAGS) -c string.C X Xbitvec$(OBJ): bitvec.C X $(CC) $(CFLAGS) -c bitvec.C X Xsplit$(OBJ): split.C vector.h cstring.h bitvec.h X $(CC) $(CFLAGS) -c split.C X END-of-Makefile echo x - ReadMe sed 's/^X//' >ReadMe << 'END-of-ReadMe' X* See comments in the Errata file on keeping up with changes in C++ and X differences in C++ compilers X these files differ from those described in the book in: X X * more classes have copy constructors X * iterators now use postfix operator X * data structures do not hold references (g++ bug?) X X* Generally, to use the data structures you simply need to place X them into a desiginated library directory, then compile X your programs with the include directory pointing to this X (using, for example, the -I switch on unix systems). X X* Note that the files string.C, random.C, bitvec.C and split.C can be X compiled into object file in facilitate compilation speed. X X* g++ and cfront differ in how they handle template functions, X I have used ifdefs based on the names __GNUG__ X to surround compiler-specific code. X you may need to experiment with this if you use a different X compiler X Xg++ comments ------------------------ X X compiling split.o seems to take a lot of memory space -- X on some machines the compiler runs out of space X X earlier versions of g++ had a problem with the recursive friend X relationship between lists and links -- this was only X curcumvented by declaraing everything public X XCFRONT comments ----------------- X X cfront gets confused with the file string.h and the X standard library of the same name. My version of string.h X has been renamed cstring.h X X X END-of-ReadMe echo x - bitvec.h sed 's/^X//' >bitvec.h << 'END-of-bitvec.h' X//====================================================================== X// File: bitvec.h X// Author: Timothy A. Budd X// Description: This file contains the interface of the bit vector X// class. X// X// Copyright (c) 1992 by Timothy A. Budd. All Rights Reserved. X// may be reproduced for any non-commercial purpose X//====================================================================== X X#ifndef BITVEC_H X#define BITVEC_H X X#include X#include X X//---------------------------------------------------------------------- X// class bitVector X// a vector of binary (0 or 1) values X// individual bits can be set or cleared, X// tested or flipped X//---------------------------------------------------------------------- X Xclass bitVector X{ Xpublic: X // constructors X bitVector(unsigned int numberOfElements); X bitVector(const bitVector & source); X X // number of legal index positions X unsigned int length() const; X X // bit set, change operations X void set(unsigned int index); X void clear(unsigned int index); X int test(unsigned int index) const; X void flip(unsigned int index); X X // set operations X void unionWith(bitVector & right); X void intersectWith(bitVector & right); X void differenceWith(bitVector & right); X int operator == (bitVector & right); X int subset(bitVector & right); X Xprotected: X vector bitValues; X X // position decoding functions X unsigned int byteNumber(unsigned int indx) const; X unsigned int mask(unsigned int indx) const; X}; X X X//---------------------------------------------------------------------- X// class charSet X// set indexed by character values X//---------------------------------------------------------------------- X Xclass charSet : public bitVector X{ Xpublic: X // constructors X charSet(); X charSet(char *); X charSet(const charSet &); X X // set protocol X void add(char ele); X void deleteAllValues(); X int includes(char ele) const; X void remove(char ele); X}; X X X#endif END-of-bitvec.h echo x - cstring.h sed 's/^X//' >cstring.h << 'END-of-cstring.h' X//====================================================================== X// File: string.h X// Author: Timothy A. Budd X// Description: This file contains the interface of the string X// class. X// X// Copyright (c) 1992 by Timothy A. Budd. All Rights Reserved. X// may be reproduced for any non-commercial purpose X//====================================================================== X X#ifndef STRING_H X#define STRING_H X X#include X X Xclass substring; // forward declaration X X X X//---------------------------------------------------------------------- X// class string X// better bounds checking, assignments which result X// in copies, comparisons using relational operators, X// high level operations such as substrings X//---------------------------------------------------------------------- X Xclass string X{ Xpublic: X // constructors X string(); X string(char); X string(int); X string(const char *); X string(const string &); X X // destructor X ~string(); X X // assignment an catenation X void operator = (const string & right); X void operator += (const string & right); X X // substring access X substring operator () (unsigned int start, unsigned int length); X X // input of an entire line of text X istream & getline(istream &); X X // number of characters in the string X unsigned int length() const; X X // access to a single character X char & operator [](unsigned int) const; X X // compare - used in relational operators X int compare(const string &) const; X X // conversion to ordinary C string X operator const char *() const; X X // allow access by substring class X friend class substring; Xprivate: X // data fields - character buffer and length X unsigned short int bufferlength; X char * buffer; X}; X X X X//---------------------------------------------------------------------- X// class substring X// facilitator class to permit access to X// portions of a string X//---------------------------------------------------------------------- X Xclass substring X{ Xpublic: X // constructors X substring(string & base, int start, int length); X substring(const substring & source); X X // assignment of string to substring X void operator = (const string &) const; X X // conversion of substring to string X operator string () const; X Xprivate: X // data areas X string & base; X const short int index; X const short int count; X}; X X X X// Function Prototypes: relational operators X Xint operator < (const string &, const string &); Xint operator <= (const string &, const string &); Xint operator != (const string &, const string &); Xint operator == (const string &, const string &); Xint operator >= (const string &, const string &); Xint operator > (const string &, const string &); X X X X// Function Prototype: concatenate operator X Xstring operator + (const string &, const string &); X X X X// Function Prototypes: character classification X Xint isUpperCase(char c); Xint isLowerCase(char c); X X X X// Function Prototypes: string conversions X Xvoid toUpper(string & word); Xvoid toLower(string & word); X X X// Function Prototype: stream input X Xistream & operator >> (istream & in, string & str); X X X X#endif END-of-cstring.h echo x - hash.h sed 's/^X//' >hash.h << 'END-of-hash.h' X//====================================================================== X// File: hash.h X// Author: Timothy A. Budd X// Description: This file contains the interface and implementation X// of the hash template classes. X// X// Copyright (c) 1992 by Timothy A. Budd. All Rights Reserved. X// may be reproduced for any non-commercial purpose X//====================================================================== X X#ifndef HASH_H X#define HASH_H X X X#include X X#include X X#include X X#include X X X X//---------------------------------------------------------------------- X// class hashVector X// vector indexed using hashed key values X// template types are type of key X// and type of value stored in vector X//---------------------------------------------------------------------- X Xtemplate class hashVector : public vector X{ Xpublic: X // constructors X hashVector(int max, int (*f)(const H &)); X hashVector(int max, int (*f)(const H &), T & initialValue); X hashVector(const hashVector & v); X X // subscript operation X T & operator [] (const H & idx); X Xprivate: X // store the hash function X int (*hashfun)(const H &); X}; X X X X//---------------------------------------------------------------------- X// class hashTable X// collection of buckets indexed by hashed values X// template types X// B - bucket type X// H - key value X// T - element held in buckets X//---------------------------------------------------------------------- X Xtemplate class hashTableIterator; X Xtemplate class hashTable X{ Xpublic: X // constructor X hashTable(unsigned int max, unsigned int (*f)(const H &)); X X // test if the set is empty X virtual int isEmpty(); X X // clear the elements of the set X virtual void deleteAllValues(); X Xprotected: X friend class hashTableIterator; X X // the actual table itself is a vector of buckets X const unsigned int tablesize; X vector buckets; X unsigned int (*hashfun)(const H &); X X // convert key into unsigned integer value in range X unsigned int hash(const H & key) const; X X // make iterator for given position in table X virtual iterator * makeIterator(unsigned int) = 0; X}; X X X X//---------------------------------------------------------------------- X// class hashTree X// hash table implemented using trees for buckets X//---------------------------------------------------------------------- X Xtemplate class hashTree : public hashTable, T, T> X{ Xpublic: X // constructor X hashTree(unsigned int max, unsigned int (*f)(const T &)); X X // add an element to the collection X void add(T newele); X X // test to see if the collect includes an element X int includes(T ele) const; X X // remove an element X void remove(T ele); X Xprotected: X virtual iterator * makeIterator(unsigned int i); X}; X X X X//---------------------------------------------------------------------- X// class hashTableIterator X// iterator protocol for hash tables X//---------------------------------------------------------------------- X Xtemplate class hashTableIterator X : public iterator X{ Xpublic: X // constructor X hashTableIterator(hashTable & v); X hashTableIterator(const hashTableIterator &); X X // iterator protocol X virtual int init(); X virtual T operator()(); X virtual int operator !(); X virtual int operator ++(); X virtual void operator =(T value); X Xprotected: X hashTable & base; X unsigned int currentIndex; X iterator * itr; X X // getNextIterator used to set internal iterator pointer X int getNextIterator(); X}; X X X X//---------------------------------------------------------------------- X// class hashTreeIterator X// iterator protocol for hash tree structures X//---------------------------------------------------------------------- X Xtemplate class hashTreeIterator X : public hashTableIterator, T, T> X{ Xpublic: X // constructor X hashTreeIterator(hashTree & x); X hashTreeIterator(const hashTreeIterator &); X}; X X X X//---------------------------------------------------------------------- X// class hashVector implementation X//---------------------------------------------------------------------- X Xtemplate hashVector:: X hashVector(int max, int (*f)(const H &)) X : vector(max), hashfun(f) X{ X // no further initialization X} X X X Xtemplate hashVector:: X hashVector(int max, int (*f)(const H &), T & initialValue) X : vector(max, initialValue), hashfun(f) X{ X // no further initialization X} X X X Xtemplate hashVector:: X hashVector(const hashVector & v) X : vector(v), hashfun(v.hashfun) X{ X // no further initialization X} X X X Xtemplate T & hashVector:: X operator [] (const H & index) X{ X // subscript a hash vector X // hash the index value before indexing vector X return vector::operator [] ((*hashfun)(index) % size); X} X X X X//---------------------------------------------------------------------- X// class hashTable implementation X//---------------------------------------------------------------------- X Xtemplate hashTable:: X hashTable(unsigned int max, unsigned int (*f)(const H &)) X : tablesize(max), buckets(max), hashfun(f) X{ X // no further initialization X} X X X Xtemplate int hashTable::isEmpty() X{ X // if any table is non-empty, return 0 X for (int i = 0; i < tablesize; i++) X if (!buckets[i].isEmpty()) X return 0; X X // all empty X return 1; X} X X X Xtemplate void hashTable:: X deleteAllValues() X{ X // delete all values from a hash table X // clear the elements from each of teh buckets X for (int i = 0; i < tablesize; i++) X buckets[i].deleteAllValues(); X} X X X Xtemplate unsigned int hashTable:: X hash(const H & key) const X{ X // return hashed value of key X return (*hashfun)(key) % tablesize; X} X X X X//---------------------------------------------------------------------- X// class hashTree implementation X//---------------------------------------------------------------------- X Xtemplate hashTree:: X hashTree(unsigned int max, unsigned int (*f)(const T &)) X : hashTable, T, T>(max, f) X{ X // no further initialization X} X X X Xtemplate void hashTree::add(T newele) X{ X // find the right bucket, then add the element X buckets[hash(newele)].add(newele); X} X X X Xtemplate int hashTree::includes(T ele) const X{ X // test to see if the collection includes an element X return buckets[hash(ele)].includes(newele); X} X X X Xtemplate void hashTree::remove(T ele) X{ X // remove an element X buckets[hash(ele)].remove(newele); X} X X X Xtemplate iterator * hashTree:: X makeIterator(unsigned int i) X{ X return new inorderTreeTraversal(buckets[i]); X} X X X X//---------------------------------------------------------------------- X// class hashTableIterator implementation X//---------------------------------------------------------------------- X Xtemplate hashTableIterator:: X hashTableIterator(hashTable & v) X : base(v), currentIndex(0), itr(0) X{ X // no further initialization X} X Xtemplate hashTableIterator:: X hashTableIterator(const hashTableIterator & x) X : base(x.base), currentIndex(x.currentIndex), itr(x.itr) X{ X // no further initialization X} X X Xtemplate int hashTableIterator:: X init() X{ X // initialize iterator, X // start search with first bucket X currentIndex = 0; X itr = 0; X return getNextIterator(); X} X X X Xtemplate T hashTableIterator:: X operator()() X{ X // return current element X return (*itr)(); X} X X X Xtemplate int hashTableIterator:: X operator !() X{ X // test if there is a current element X return itr != 0; X} X X X Xtemplate int hashTableIterator:: X operator ++() X{ X // see if current iterator can be advanced X if (itr && (*itr)++) X return 1; X X // if not, get next iterator X currentIndex++; X return getNextIterator(); X} X X X Xtemplate void hashTableIterator:: X operator=(T val) X{ X // change the current value X (*itr) = val; X} X X X Xtemplate int hashTableIterator:: X getNextIterator() X{ X // if there is an old iterator, delete it X if (itr != 0) X delete itr; X X // now search for a new one X for (; currentIndex < base.tablesize; currentIndex++) X { X // generate a new iterator at the current point X itr = base.makeIterator(currentIndex); X assert(itr != 0); X X // if it has at least one element, we're done X if (itr->init()) X return 1; X X // otherwise delete it, try again X delete itr; X } X X // all out of iterators, can quit X itr = 0; X return 0; X} X X X X//---------------------------------------------------------------------- X// class hashTreeIterator implementation X//---------------------------------------------------------------------- X Xtemplate hashTreeIterator::hashTreeIterator(hashTree & x) X : hashTableIterator, T, T>(x) X{ X // no further initialization X} X Xtemplate hashTreeIterator:: X hashTreeIterator(const hashTreeIterator & x) X : hashTableIterator, T, T>(x) X{ X // no further initialization X} X X X//---------------------------------------------------------------------- X// miscellaneous template functions X//---------------------------------------------------------------------- X X// bucket sort (version #1) X X# ifdef __GNUG__ X X# include X X# endif X X# ifndef __GNUG__ X Xtemplate void bucketSort(vector & data, X unsigned int tablesize, unsigned int (*f)(const T &)); X Xtemplate void bucketSort(vector & data, X unsigned int (*f)(const T &)); X X# endif X X#endif END-of-hash.h echo x - iterator.h sed 's/^X//' >iterator.h << 'END-of-iterator.h' X//====================================================================== X// File: iterator.h X// Author: Timothy A. Budd X// Description: This file contains the iterator template class X// X// Copyright (c) 1992 by Timothy A. Budd. All Rights Reserved. X// may be reproduced for any non-commercial purpose X//====================================================================== X X#ifndef ITERATOR_H X#define ITERATOR_H X X X X//---------------------------------------------------------------------- X// class iterator X// define the protocol to be used by all iterators X// subclasses must implement each of the five X// iterator methods X//---------------------------------------------------------------------- X Xtemplate class iterator X{ Xpublic: X // initialization X virtual int init() = 0; X X // test if there is a current element X virtual int operator !() = 0; X X // current element X virtual T operator ()() = 0; X X // find next element X virtual int operator ++() = 0; X X // change current element X virtual void operator =(T newValue) = 0; X}; X X#endif END-of-iterator.h echo x - labeledVertex.h sed 's/^X//' >labeledVertex.h << 'END-of-labeledVertex.h' X//================================================================== X// File: labeledVertex.h X// Author: Timothy A. Budd X// Platform: Cfront X// Description: Template Description of labeled graph vertex X// Copyright (c) 1992 by Timothy A. Budd, All Rights Reserved X// Permission granted for duplication if not for profit X//================================================================== X X# ifndef labeldVertexH X# define labeldVertexH X X// X// weighted graph vertices X// X X# include X X// X// class labeledVertex X// vertex maintaining arcs with edge weights X// X Xtemplate class labeledVertex { Xpublic: X T value; X X // constructors X labeledVertex(); X labeledVertex(T init); X labeledVertex(const labeledVertex & x); X X // collect the set of neighbor arcs X dictionary arcs; X X // add an arc X void addArc(labeledVertex * to, A label); X}; X X Xtemplate int operator == X (const labeledVertex & left, const labeledVertex & right); X Xtemplate XlabeledVertex::labeledVertex() X{ X} X Xtemplate XlabeledVertex::labeledVertex(T init) : value(init) X{ X} X Xtemplate XlabeledVertex::labeledVertex(const labeledVertex & x) X : value(x.value) X{ X} X Xtemplate Xvoid labeledVertex::addArc(labeledVertex * to, A label) X{ X arcs[to] = label; X} X Xtemplate int operator == X (const labeledVertex & left, const labeledVertex & right) X{ X return left.value == right.value; X} X X# endif END-of-labeledVertex.h echo x - list.h sed 's/^X//' >list.h << 'END-of-list.h' X//====================================================================== X// File: list.h X// Author: Timothy A. Budd X// Description: This file contains the interface of the list X// classes. X// X// Copyright (c) 1992 by Timothy A. Budd. All Rights Reserved. X// may be reproduced for any non-commercial purpose X//====================================================================== X X#ifndef LIST_H X#define LIST_H X X#include X#include X X//---------------------------------------------------------------------- X// class list X// arbitrary size lists of elements X// permits insertion and removal only X// from the front of the list X//---------------------------------------------------------------------- X Xtemplate class link; Xtemplate class listIterator; X Xtemplate class list X{ Xpublic: X // constructors X list(); X list(const list & source); X virtual ~list(); X X // operations X void add(T value); X virtual void deleteAllValues(); X list * duplicate() const; X T firstElement() const; X virtual int includes(T value) const; X int isEmpty() const; X virtual void removeFirst(); X Xprotected: X // data field X link * ptrToFirstLink; X X // friends X friend class listIterator; X}; X X X X//---------------------------------------------------------------------- X// class link X// facilitator for operations on lists X// maintains a single element for the linked list class X//---------------------------------------------------------------------- X Xtemplate class link X{ Xpublic: X // insert a new element following the current value X link * insert(T val); X Xprivate: X // constructor X link(T linkValue, link * nextPtr); X link(const link &); X X // duplicate X link * duplicate() const; X X // data areas X T value; X link * ptrToNextLink; X X // friends X friend class list; X friend class listIterator; X}; X X X X//---------------------------------------------------------------------- X// class listIterator X// implements iterator protocol for linked lists X// also permits removal and addition of elements X//---------------------------------------------------------------------- X Xtemplate class listIterator : public iterator X{ Xpublic: X // constructor X listIterator(list & aList); X listIterator(const listIterator &); X X // iterator protocol X virtual int init(); X virtual T operator ()(); X virtual int operator !(); X virtual int operator ++(); X virtual void operator =(T value); X X // new methods specific to list iterators X void removeCurrent(); X void addBefore(T newValue); X void addAfter(T newValue); X Xprotected: X // data areas X link * currentLink; X link * previousLink; X list & theList; X}; X X X//---------------------------------------------------------------------- X// class orderedList X// a list structure where each element X// is maintained in sequence based on the X// less-than comparison operator X//---------------------------------------------------------------------- X Xtemplate class orderedList : public list X{ Xpublic: X // change the addition method X void add(T value); X}; X X//---------------------------------------------------------------------- X// class doubleEndedList X// a variation on lists - can add elements to end X// as well as to front X//---------------------------------------------------------------------- X Xtemplate class doubleEndedList : public list { Xpublic: X // constructors X doubleEndedList (); X doubleEndedList (const doubleEndedList &); X X // override the following methods from class list X virtual void add (T value); X virtual void deleteAllValues (); X virtual void removeFirst (); X X // add a new element to the end of the list X void addToEnd (T value); X Xprotected: X // data area -- link to end X link * ptrToLastLink; X}; X X//---------------------------------------------------------------------- X// class list implementation X//---------------------------------------------------------------------- X Xtemplate list::list() : ptrToFirstLink(0) X{ X // no further initialization X} X X X Xtemplate list::~list() X{ X // empty all elements from the list X deleteAllValues(); X} X X X Xtemplate void list::add(T val) X{ X // add a new value to the front of a linked list X ptrToFirstLink = new link(val, ptrToFirstLink); X assert(ptrToFirstLink != 0); X} X X X Xtemplate void list::deleteAllValues() X{ X // clear all items from the list X link * next; X X for (link * p = ptrToFirstLink; p != 0; p = next) X { X // delete the element pointed to by p X next = p->ptrToNextLink; X p->ptrToNextLink = 0; X delete p; X } X X // mark that the list contains no elements X ptrToFirstLink = 0; X} X X Xtemplate list * list::duplicate() const X{ X list * newlist = new list; X assert(newlist != 0); X X // copy list X if (ptrToFirstLink) X newlist->ptrToFirstLink = ptrToFirstLink->duplicate(); X X // return the new list X return newlist; X} X Xtemplate list::list(const list & source) X{ X // duplicate elements from source list X if (source.isEmpty()) X ptrToFirstLink = 0; X else X { X link * firstLink = source.ptrToFirstLink; X ptrToFirstLink = firstLink->duplicate(); X } X} X Xtemplate T list::firstElement() const X{ X // return first value in list X assert(ptrToFirstLink != 0); X return ptrToFirstLink->value; X} X X X Xtemplate int list::includes(T v) const X{ X // loop to test each element X for (link * p = ptrToFirstLink; p; p = p->ptrToNextLink) X if (v == p->value) X return 1; X X // not found X return 0; X} X X X Xtemplate int list::isEmpty() const X{ X // test to see if the list is empty X // list is empty if the pointer to the first link is null X return ptrToFirstLink == 0; X} X X X Xtemplate void list::removeFirst() X{ X // make sure there is a first element X assert(ptrToFirstLink != 0); X X // save pointer to the removed node X link * p = ptrToFirstLink; X X // reassign the ptrToFirstLink node X ptrToFirstLink = p->ptrToNextLink; X X // recover memory used by the first element X delete p; X} X X X//---------------------------------------------------------------------- X// class link implementation X//---------------------------------------------------------------------- X Xtemplate link * link::insert(T val) X{ X // insert a new link after current node X ptrToNextLink = new link(val, ptrToNextLink); X X // check that allocation was successful X assert(ptrToNextLink != 0); X return ptrToNextLink; X} X Xtemplate link::link(T val, link * nxt) X : value(val), ptrToNextLink(nxt) X{ X // create and initialize a new link field X} X Xtemplate link::link(const link & source) X : value(source.value), ptrToNextLink(source.ptrToNextLink) X{ X} X Xtemplate link * link::duplicate() const X{ X link * newlink; X X // if there is a next field. copy remainder of list X if (ptrToNextLink != 0) X newlink = new link(value, ptrToNextLink->duplicate()); X else X newlink = new link(value, 0); X X // check that allocation was successful X //assert(newlink != 0); X return newlink; X} X X//---------------------------------------------------------------------- X// class listIterator implementation X//---------------------------------------------------------------------- X Xtemplate listIterator::listIterator(list & aList) X : theList(aList) X{ X // create and initialize a new list X init(); X} X Xtemplate listIterator::listIterator(const listIterator & x) X : theList(x.theList) X{ X init(); X} X Xtemplate int listIterator::init() X{ X // set the iterator to the first element in the list X previousLink = 0; X currentLink = theList.ptrToFirstLink; X return currentLink != 0; X} X X X Xtemplate T listIterator::operator ()() X{ X // return value of current element X // check to see if there is a current element X assert(currentLink != 0); X X // return value associated with current element X return currentLink->value; X} X X X Xtemplate int listIterator::operator !() X{ X // test for termination of the iterator X // if current link references a removed value, X // update current to point to next position X if (currentLink == 0) X if (previousLink != 0) X currentLink = previousLink->ptrToNextLink; X X // now see if currentLink is valid X return currentLink != 0; X} X X X Xtemplate int listIterator::operator ++() X{ X // move current pointer to nect element X // special processing if current link is deleted X if (currentLink == 0) X { X if (previousLink == 0) X currentLink = theList.ptrToFirstLink; X else X currentLink = previousLink->ptrToNextLink; X } X else X { X // advance pointer X previousLink = currentLink; X currentLink = currentLink->ptrToNextLink; X } X X // return true if we have a valid current element X return currentLink != 0; X} X X X Xtemplate void listIterator::operator =(T val) X{ X // modify value of current element X assert(currentLink != 0); X X // modify value of the current link X currentLink->value = val; X} X X X Xtemplate void listIterator::removeCurrent() X{ X // remove the current element from a list X // make sure there is a current element X assert(currentLink != 0); X X // case 1, removing first element X if (previousLink == 0) X theList.ptrToFirstLink = currentLink->ptrToNextLink; X X // case 2, not removing the first element X else X previousLink->ptrToNextLink = currentLink->ptrToNextLink; X X // delete current node X delete currentLink; X X // and set current pointer to null X currentLink = 0; X} X X X Xtemplate void listIterator::addBefore(T val) X{ X // a a new element to list before current value X // case 1, not at start X if (previousLink) X previousLink = previousLink->insert(val); X X // case 2, at start of list X else X { X //theList.list::add(val); X // g++ change X theList.add(val); X previousLink = theList.ptrToFirstLink; X currentLink = previousLink->ptrToNextLink; X } X} X X X Xtemplate void listIterator::addAfter(T val) X{ X // a a new element to list after current value X // case 1, not at start X if (currentLink != 0) X currentLink->insert(val); X X // case 2, at end of list X else if (previousLink != 0) X currentLink = previousLink->insert(val); X X // case 3, start of list X else X //theList.list::add(val); X // g++ change X theList.add(val); X} X X X X//---------------------------------------------------------------------- X// class orderedList implementation X//---------------------------------------------------------------------- X Xtemplate void orderedList::add(T val) X{ X // add a new value to an ordered list X // loop over values smaller than current X listIterator itr(*this); X X for (itr.init(); !itr; ++itr) X if (val < itr()) X { X // found location to insert value X itr.addBefore(val); X return; X } X X // add to end of list if not yet inserted X itr.addBefore(val); X} X X//---------------------------------------------------------------------- X// class doubleEndedList implementation X//---------------------------------------------------------------------- X Xtemplate doubleEndedList::doubleEndedList() X : list() X{ X ptrToLastLink = 0; X} X Xtemplate doubleEndedList:: X doubleEndedList(const doubleEndedList & x) X : list(x), ptrToLastLink(x.ptrToLastLink) X{ X} X Xtemplate void doubleEndedList::add(T val) X{ // add an element to the front of a double ended list X // only need to handle addition to empty list X X if (isEmpty()) { X list::add(val); X ptrToLastLink = ptrToFirstLink; X } X else X list::add(val); X} X Xtemplate void doubleEndedList::addToEnd(T val) X{ X // add a new element to the end of a double ended list X // if there is an end, add to it X X if (ptrToLastLink != 0) X ptrToLastLink = ptrToLastLink->insert(val); X X // otherwise, just add to front X else X add(val); X} X Xtemplate void doubleEndedList::deleteAllValues() X{ X // delete all values from collection X // invoke the list method to do the actual work X X list::deleteAllValues(); X X // then set the pointer to the last element to zero X X ptrToLastLink = 0; X} X Xtemplate void doubleEndedList::removeFirst() X{ X // remove the first element from double ended list X // invoke the method from list to do the work X X list::removeFirst(); X X // only do something different if we removed last element X X if (isEmpty()) X ptrToLastLink = 0; X} X X// X// ==========insertion sort -- this is done differently by X// cfront and g++ X X# ifdef __GNUG__ X X# include X X# endif X X# ifndef __GNUG__ X X# include Xtemplate void listInsertionSort(vector & v); X X# endif X X#endif END-of-list.h echo x - oldassert.h sed 's/^X//' >oldassert.h << 'END-of-oldassert.h' X// X// IMPORTANT -- This file is here just to get around what X// is probably simply a local implementation bug X// you should remove this file and only use X// if compiling produces strange link errors X// X X X#ifdef assert X#undef assert X#endif X#ifdef _assert X#undef _assert X#endif X X#define assert(e) ((void)0) X END-of-oldassert.h echo x - openHashTable.h sed 's/^X//' >openHashTable.h << 'END-of-openHashTable.h' X//================================================================== X// File: openHashTable.h X// Author: Timothy A. Budd X// Platform: Cfront X// Description: Template Description of open addressing hash table ADT X// Copyright (c) 1992 by Timothy A. Budd, All Rights Reserved X// Permission granted for duplication if not for profit X//================================================================== X X# ifndef openHashTableH X# define openHashTableH X X// X// class openHashTable X// external hash table X// type T must supply function ``isEmpty'' and equality test X// X X# include X Xtemplate class openHashTableIterator; X Xtemplate class openHashTable { Xpublic: X // constructor X openHashTable(const string & name, unsigned int (*f)(const T &)); X X // operations X void create(unsigned int size); X int add(const T &); X int includes(T &); X void remove(const T &); X Xprivate: X friend class openHashTableIterator; X // data values - hash function, random access stream and size of file X unsigned int (*hashfun)(const T &); X rstream rfile; X unsigned int size; X}; X X# endif END-of-openHashTable.h echo x - priorque.h sed 's/^X//' >priorque.h << 'END-of-priorque.h' X//====================================================================== X// File: priorque.h X// Author: Timothy A. Budd X// Description: This file contains the interface of the priorityQueue X// classes. X// X// Copyright (c) 1992 by Timothy A. Budd. All Rights Reserved. X// may be reproduced for any non-commercial purpose X//====================================================================== X X#ifndef PRIORQUE_H X#define PRIORQUE_H X X#include X#include X#include X#include X X X X//---------------------------------------------------------------------- X// class priorityQueue X// ordered collection of values permitting X// rapid removal of smallest value X//---------------------------------------------------------------------- X Xtemplate class priorityQueue X{ Xpublic: X // add a value to the collection X virtual void add(T value) = 0; X X // return and remove the smallest element from the collection X T deleteMin(); X X // indicate whether there are elements in the collection X virtual int isEmpty() const = 0; X X // return the smallest element in the collection X virtual T min() const = 0; X X // remove the smallest element from the collection X virtual void removeMin() = 0; X}; X X X X//---------------------------------------------------------------------- X// class priorityQueueList X// implement priority queue protocol X// using a linked list structure X//---------------------------------------------------------------------- X Xtemplate class priorityQueueList : public priorityQueue X{ Xpublic: X // constructors X priorityQueueList(); X priorityQueueList(const priorityQueueList & v); X X // priority queue protocol X virtual void add(T value); X virtual int isEmpty() const; X virtual T min() const; X virtual void removeMin(); X Xprivate: X // data area X orderedList lst; X}; X X X X//---------------------------------------------------------------------- X// class heap X// a priority queue managed as a vector heap X//---------------------------------------------------------------------- X Xtemplate class heap : public priorityQueue X{ Xpublic: X // constructors X heap(unsigned int maxsize); X heap(const heap &); X X // priority queue protocol X virtual void add(T value); X virtual int isEmpty() const; X virtual T min() const; X virtual void removeMin(); X X // delete all values X void deleteAllValues(); X Xprivate: X // data areas X vector data; X unsigned int heapmax; X unsigned int heapsize; X}; X X X X//---------------------------------------------------------------------- X// class skewHeap X// heap priority implemented using skew heap merge X// operations X//---------------------------------------------------------------------- X Xtemplate class skewHeap : public priorityQueue X{ Xpublic: X // constructors and destructor X skewHeap(); X skewHeap(const skewHeap & v); X virtual ~skewHeap(); X X // priority queue protocol X virtual void add(T value); X virtual int isEmpty() const; X virtual T min() const; X virtual void removeMin(); X X // delete all values X void deleteAllValues(); X X // merge two heaps together X void add(skewHeap & secondHeap); X X // root of heap X node * root; X X // private method to merge two heaps X node * merge(node *, node *); X}; X X X X//---------------------------------------------------------------------- X// class prioityQueue implementation X//---------------------------------------------------------------------- X Xtemplate T priorityQueue::deleteMin() X{ X // return and remove the smallest element X T result = min(); X removeMin(); X return result; X} X X X X//---------------------------------------------------------------------- X// class prioityQueueList implementation X//---------------------------------------------------------------------- X Xtemplate priorityQueueList::priorityQueueList() X{ X // no initialization required X} X X X Xtemplate priorityQueueList::priorityQueueList( X const priorityQueueList & source) : lst(source.lst) X{ X# if 0 X // remove all values from the priority queue X lst.deleteAllValues(); X X // duplicate elements from source list X listIterator itr(source.lst); X X for (itr.init(); !itr; ++itr) X add(itr()); X# endif X} X X X Xtemplate void priorityQueueList::add(T value) X{ X // add item to queue by adding to list X lst.add(value); X} X X X Xtemplate int priorityQueueList::isEmpty() const X{ X // queue is empty if list is empty X return lst.isEmpty(); X} X X X Xtemplate T priorityQueueList::min() const X{ X // smallest item is first element in list X return lst.firstElement(); X} X X X Xtemplate void priorityQueueList::removeMin() X{ X // smallest item is first element in list X lst.removeFirst(); X} X X X X//---------------------------------------------------------------------- X// class heap implementation X//---------------------------------------------------------------------- X Xtemplate heap::heap(unsigned int maxsize) X : data(maxsize), heapmax(maxsize), heapsize(0) X{ X // no further initialization X} X X X Xtemplate heap::heap(const heap & source) X : data(source.data), heapmax(source.heapmax), heapsize(source.heapsize) X{ X //data = source.data; X //heapmax = source.heapmax; X //heapsize = source.heapsize; X} X X X Xtemplate void heap::add(T newele) X{ X // add a new element to the heap X // make sure there is room for new element X if (heapsize + 1 >= heapmax) X { X data.setSize(data.length() + 5); X heapmax += 5; X } X X // value starts out in last position X unsigned int position = heapsize++; X X // inv: position <= 0 and < heapmax X X // now percolate up X while (position > 0 && newele < data[(position-1)/2]) X { X data[position] = data[(position-1)/2]; X X // inv: tree rooted at "position" is a heap X position = (position - 1) / 2; X } X X // found location, add new element X data[position] = newele; X X // inv: tree rooted at position is a heap X // inv: data holds a heap X for (int ii = 0; ii < heapsize; ii++) X cout << data[ii] << " & "; X cout << "\\\\\n"; X} X X X Xtemplate int heap::isEmpty() const X{ X // heap is empty if heapsize is zero X return heapsize == 0; X} X X X Xtemplate T heap::min() const X{ X // smallest item is first element in vector X return data[0]; X} X X X// g++ and CFRONT handle template functions differently X# ifndef __GNUG__ X Xtemplate void buildHeap( X vector & data, int heapsize, int position); X X# endif X X Xtemplate void heap::removeMin() X{ X // remove the smallest element from a heap X // move the last element into the first position X data[0] = data[--heapsize]; X X // then move into position X buildHeap(data, heapsize, 0); X} X X X Xtemplate void heap::deleteAllValues() X{ X // heap is empty if heapsize is zero X heapsize = 0; X} X X X X//---------------------------------------------------------------------- X// class skewHeap implementation X//---------------------------------------------------------------------- X Xtemplate skewHeap::skewHeap() X{ X root = 0; X} X X X Xtemplate skewHeap::skewHeap(const skewHeap & source) X{ X // duplicate tree from source X root = source.root->copy(); X} X X X Xtemplate skewHeap::~skewHeap() X{ X deleteAllValues(); X} X X X Xtemplate void skewHeap::add(T val) X{ X // to add a new value, simply merge with an empty tree X // current tree X node * newnode = new node(val); X assert(newnode != 0); X root = merge(root, newnode); X} X X X Xtemplate int skewHeap::isEmpty() const X{ X // heap is empty if root is zero X return root == 0; X} X X X Xtemplate T skewHeap::min() const X{ X // smallest item is first at the root X assert(! isEmpty()); X return root->value; X} X X Xtemplate void skewHeap::removeMin() X{ X // remove the smallest element from a skew heap X assert(!isEmpty()); X X node * top = root; X root = merge(root->right(), root->left()); X delete top; X} X X X Xtemplate void skewHeap::deleteAllValues() X{ X // releasing the tree at the root deletes all the values X if (root) X { X root->release(); X root = 0; X } X} X X X Xtemplate void skewHeap::add(skewHeap & secondHeap) X{ X // merge elements from a second heap into current heap X root = merge(root, secondHeap.root); X X // empty values from second heap X secondHeap.root = 0; X} X X X Xtemplate node * skewHeap::merge( X node * h1, node * h2) X{ X // merge two skew heaps to form a new heap X // if either tree is empty, return the other X if (!h1) return h2; X if (!h2) return h1; X X // assume smallest is root h1 X if (h2->value < h1->value) X return merge(h2, h1); X X // reverse children and recur X node * lchild = h1->left(); X X if (lchild) X { X h1->left(merge(h1->right(), h2)); X h1->right(lchild); X } X else // no left child X h1->left(h2); X X return h1; X} X X X//---------------------------------------------------------------------- X// function: heapSort X//---------------------------------------------------------------------- X X# ifdef __GNUG__ X X# include X X X# endif X X# ifndef __GNUG__ X Xtemplate void heapSort(vector & data); X X# endif X X#endif END-of-priorque.h echo x - queue.h sed 's/^X//' >queue.h << 'END-of-queue.h' X//================================================================== X// File: queue.h X// Author: Timothy A. Budd X// Platform: Cfront X// Description: Template Description of Abstract Queue ADT X// Copyright (c) 1992 by Timothy A. Budd, All Rights Reserved X// Permission granted for duplication if not for profit X//================================================================== X X# ifndef queueH X# define queueH X Xtemplate Xclass queue { Xpublic: X // protocol for queue operations X virtual void deleteAllValues () = 0; X virtual T dequeue () = 0; X virtual void enqueue (T value) = 0; X virtual T front () const = 0; X virtual int isEmpty () const = 0; X}; X X# include X Xtemplate class queueVector : public queue { Xpublic: X // constructor requires a starting size X queueVector(unsigned int max); X queueVector(const queueVector & x); X X // implement queue protocol X virtual void deleteAllValues (); X virtual T dequeue (); X virtual void enqueue (T value); X virtual T front () const; X virtual int isEmpty () const; X Xprivate: X vector data; X const unsigned int max; X unsigned int nextSlot; X unsigned int nextUse; X}; X X# include X X// X// class queueList X// queue implemented using list operations X// X Xtemplate class queueList : public queue { Xpublic: X // constructors X queueList(); X queueList(const queueList & v); X X // protocol for queue operations X virtual void deleteAllValues (); X virtual T dequeue (); X virtual void enqueue (T value); X virtual T front () const; X virtual int isEmpty () const; X Xprivate: X doubleEndedList data; X}; X X//================================================================== X X# include X Xtemplate queueVector::queueVector(unsigned int size) X : max(size), data(size) X{ X // make sure queue is initially empty X deleteAllValues(); X} X Xtemplate queueVector::queueVector(const queueVector & v) : X data(v.data), max(v.max), nextSlot(v.nextSlot), nextUse(v.nextUse) X{ X // no further initialization X} X Xtemplate void queueVector::deleteAllValues() X{ X nextSlot = 0; X nextUse = 0; X} X Xtemplate void queueVector::enqueue(T val) X{ X data[nextSlot++] = val; X if (nextSlot >= max) X nextSlot = 0; X // make sure queue has not overflowed X assert(nextSlot != nextUse); X} X Xtemplate T queueVector::front() const X{ X // can not return a value from an empty queue X assert(! isEmpty()); X return data[nextUse]; X} X Xtemplate T queueVector::dequeue() X{ X // can not dequeue from an empty queue X assert(! isEmpty()); X int dataloc = nextUse; X nextUse++; X if (nextUse >= max) X nextUse = 0; X return data[dataloc]; X} X Xtemplate int queueVector::isEmpty() const X{ X // queue is empty if next slot is X // pointing to same location as next use X return nextSlot == nextUse; X} X X//================================================================== X Xtemplate queueList::queueList() : data() X{ X // no further initialization X} X Xtemplate queueList::queueList(const queueList & v) X : data(v.data) X{ X // no further initialization X} X Xtemplate void queueList::deleteAllValues() X{ X data.deleteAllValues(); X} X X Xtemplate void queueList::enqueue(T value) X{ X data.addToEnd(value); X} X Xtemplate T queueList::front() const X{ X return data.firstElement(); X} X Xtemplate int queueList::isEmpty() const X{ X return data.isEmpty(); X} X Xtemplate T queueList::dequeue() X{ X T result = data.firstElement(); X data.removeFirst(); X return result; X} X X// X// class queueRingBuffer - X// implementation of queue X// using ring buffers X// X Xtemplate class queueRingBuffer : public queue { X Xpublic: X // constructor takes initial size X queueRingBuffer(unsigned int); X ~queueRingBuffer(); X X // protocol for queue operations X virtual void deleteAllValues (); X virtual T dequeue (); X virtual void enqueue (T value); X virtual T front () /* const */; X virtual int isEmpty () /* const */; X Xprivate: X link * lastFilled; X link * lastFree; X}; X Xtemplate inline void queueRingBuffer::deleteAllValues() X{ X lastFree = lastFilled; X} X Xtemplate inline int queueRingBuffer::isEmpty() /* const */ X{ X // queue is empty if pointers are equal X return lastFree == lastFilled; X} X Xtemplate queueRingBuffer::~queueRingBuffer() X{ link * p = lastFree; X link * next; X X // walk around the circle deleting nodes X while (p->ptrToNextLink != lastFree) { X next = p->ptrToNextLink; X delete p; X p = next; X } X} X Xtemplate queueRingBuffer::queueRingBuffer(unsigned int max) X{ X // create the first link X T initialvalue; X lastFree = new link(initialvalue, 0); X assert(lastFree != 0); X lastFilled = lastFree; X // make value point to itself X lastFilled->ptrToNextLink = lastFilled; X // now add the remainder of the elements X while (max-- > 0) X lastFilled->insert(initialvalue); X} X Xtemplate T queueRingBuffer::dequeue() X{ X // cannot dequeue from empty queue X assert(! isEmpty()); X // advance last free position X lastFree = lastFree->ptrToNextLink; X // return value stored in last free position X return lastFree->value; X} X Xtemplate T queueRingBuffer::front() /* const */ X{ X // cannot take front of empty queue X assert(! isEmpty()); X link * ptrToFront = lastFree->ptrToNextLink; X return ptrToFront->value; X} X Xtemplate void queueRingBuffer::enqueue(T val) X{ X // first check for potential overflow X if (lastFilled->ptrToNextLink == lastFree) X lastFilled = lastFilled->insert(val); X else { X // simply advance the last filled pointer X lastFilled = lastFilled->ptrToNextLink; X lastFilled->value = val; X } X} X X# endif X END-of-queue.h echo x - random.h sed 's/^X//' >random.h << 'END-of-random.h' X//====================================================================== X// File: random.h X// Author: Timothy A. Budd X// Description: This file contains the interface of the random X// number generator class. X// X// Copyright (c) 1992 by Timothy A. Budd. All Rights Reserved. X// may be reproduced for any non-commercial purpose X//====================================================================== X X#ifndef RANDOM_H X#define RANDOM_H X X# include X X X//---------------------------------------------------------------------- X// class random X// random numbers generated using X// linear congruent algorithm X// assumes 16-bit values X//---------------------------------------------------------------------- X Xclass random X{ Xpublic: X // constructors X random(); X random(unsigned int); X X // methods used to get values X unsigned int randomInteger(); X double randomReal(); X double between(double, double); X int between(int, int); X X int weightedDiscrete(vector &); X Xprivate: X unsigned int seed; X}; X X#endif END-of-random.h echo x - rational.h sed 's/^X//' >rational.h << 'END-of-rational.h' X//================================================================== X// File: rational.h X// Author: Timothy A. Budd X// Description: interface for the rational number X// data abstraction X// Copyright (c) 1992 by Timothy A. Budd, All Rights Reserved X// Permission Granted for Duplication if not for profit X//================================================================== X# ifndef RATIONAL_H X# define RATIONAL_H X X// forward references X Xclass ostream; Xclass istream; X X// X// class rational X// rational number data abstraction X// X Xclass rational { Xpublic: X // constructors X rational (); X rational (int); X rational (int, int); X rational (const rational &); X X // accessor functions X int numerator () const; X int denominator () const; X X // assignments X void operator = (const rational &); X void operator += (const rational &); X void operator -= (const rational &); X void operator *= (const rational &); X void operator /= (const rational &); X X // comparison X int compare (const rational &) const; X X // conversions X operator float () const; X Xprivate: X // data areas X int top; X int bottom; X X // operations used internally X void normalize (); X}; X X// X// function prototypes X// X Xrational operator + (const rational &, const rational &); Xrational operator - (const rational &, const rational &); Xrational operator * (const rational &, const rational &); Xrational operator / (const rational &, const rational &); Xrational operator - (const rational &); X X// comparison operations Xint operator == (const rational &, const rational &); Xint operator != (const rational &, const rational &); Xint operator < (const rational &, const rational &); Xint operator <= (const rational &, const rational &); Xint operator > (const rational &, const rational &); Xint operator >= (const rational &, const rational &); X X// input and output functions Xostream & operator << (ostream &, const rational &); Xistream & operator >> (istream &, rational &); X Xint floor(const rational &); X X// X// inline functions X// X Xinline rational::rational() : top(0), bottom(1) X{ X // no further initialization required X} X Xinline rational::rational(int numerator) : top(numerator), bottom(1) X{ X // no further initialization required X} X Xinline rational::rational(const rational & value) X : top(value.top), bottom(value.bottom) X{ X // no further initialization required X} X Xinline int rational::numerator() const X{ X // return numerator field of rational number X return top; X} X Xinline int rational::denominator() const X{ X // return denominator field of rational number X return bottom; X} X X#endif END-of-rational.h echo x - rstream.h sed 's/^X//' >rstream.h << 'END-of-rstream.h' X//================================================================== X// File: rstream.h X// Author: Timothy A. Budd X// Platform: Cfront X// Description: Template Description of random access stream ADT X// Copyright (c) 1992 by Timothy A. Budd, All Rights Reserved X// Permission granted for duplication if not for profit X//================================================================== X X// X// class rstream X// randomly accessed streams X// X X# ifndef rstreamH X# define rstreamH X Xclass string; X# include X Xtemplate class rstream { Xpublic: X // constructor X rstream(const string & name); X X // access to element X int get(unsigned int index, T & value); X X // placement of element X void put(unsigned int index, const T & value); X X // number of elements X unsigned int length(); X Xprivate: X fstream theStream; X}; X X# include X Xtemplate class rstreamIterator : public iterator { Xpublic: X // constructor X rstreamIterator(rstream &); X rstreamIterator(const rstreamIterator &); X X // iterator protocol X virtual int init (); X virtual T operator() (); X virtual int operator ! (); X virtual int operator ++ (); X virtual void operator = (T value); X Xprivate: X unsigned int index; X rstream & baseStream; X}; X X# endif END-of-rstream.h echo x - set.h sed 's/^X//' >set.h << 'END-of-set.h' X//====================================================================== X// File: set.h X// Author: Timothy A. Budd X// Description: This file contains the interface and implementation X// of the set and bag template classes. X// X// Copyright (c) 1992 by Timothy A. Budd. All Rights Reserved. X// may be reproduced for any non-commercial purpose X//====================================================================== X X#ifndef SET_H X#define SET_H X X#include X#include X#include X#include X X X//---------------------------------------------------------------------- X// class setList X// set protocol built on top of list implementation X//---------------------------------------------------------------------- X Xtemplate class setList : public list X{ Xpublic: X // add an item to the set X virtual void add(T val); X X // removal test X virtual void remove(T); X X // union formation X void unionWith(setList &); X X // intersection X void intersectWith(setList &); X X // difference between sets X void differenceFrom(setList &); X X // subset test X int subset(setList &); X}; X X X X//---------------------------------------------------------------------- X// class setTable X// set protocol built out of hash tables X//---------------------------------------------------------------------- X Xtemplate class setTable : public hashTable, T, T> X{ Xpublic: X // constructor X setTable(unsigned int max, unsigned int (*f)(const T &)); X X // implement set protocol X void add(T val); X void differenceFrom(setTable &); X int includes(T val) const; X void intersectWith(setTable &); X void remove(T val); X void unionWith(setTable &); X int subset(setTable &) const; X Xprotected: X // make an iterator X iterator * makeIterator(unsigned int i); X}; X X X X//---------------------------------------------------------------------- X// set template functions (for class iterator) X//---------------------------------------------------------------------- X Xtemplate void setUnionWith(ST & set, X iterator & itr) X{ X // simply add every element from the argument iterator X for (itr.init(); ! itr; ++itr) X set.add(itr()); X} X X X Xtemplate void setDifferenceFrom(ST & set, X iterator & itr) X{ X // test every element to see if it is in the receiver X for (itr.init(); ! itr; ++itr) X // if current set has it X if (set.includes(itr())) X // then remove it X set.remove(itr()); X} X X X Xtemplate int setSubset(ST & set, X iterator & itr) X{ X // every element of right must also be in receiver X for (itr.init(); ! itr; ++itr) X // if set does not have it X if (! set.includes(itr())) X // then can't be a subset X return 0; X X // everything checks out, must be a subset X return 1; X} X X X Xtemplate void setIntersectWith(ST & set, X iterator & itr) X{ X // make a list of elements in the difference X list difference; X X // for each element in iterator X for (itr.init(); ! itr; ++itr) X // if it is not in set X if (! set.includes(itr())) X // then save it X difference.add(itr()); X X // now remove elements from the difference X listIterator litr(difference); X X for (litr.init(); ! litr; ++litr) X set.remove(litr()); X} X X X X//---------------------------------------------------------------------- X// set template functions (for class listIterator) X//---------------------------------------------------------------------- X Xtemplate void setUnionWith(ST & set, X listIterator & itr) X{ X // simply add every element from the argument iterator X for (itr.init(); ! itr; ++itr) X set.add(itr()); X} X X X Xtemplate void setDifferenceFrom(ST & set, X listIterator & itr) X{ X // test every element to see if it is in the receiver X for (itr.init(); ! itr; ++itr) X // if current set has it X if (set.includes(itr())) X // then remove it X set.remove(itr()); X} X X X Xtemplate int setSubset(ST & set, X listIterator & itr) X{ X // every element of right must also be in receiver X for (itr.init(); ! itr; ++itr) X // if set does not have it X if (! set.includes(itr())) X // then can't be a subset X return 0; X X // everything checks out, must be a subset X return 1; X} X X X Xtemplate void setIntersectWith(ST & set, X listIterator & itr) X{ X // make a list of elements in the difference X list difference; X X // for each element in iterator X for (itr.init(); ! itr; ++itr) X // if it is not in set X if (! set.includes(itr())) X // then save it X difference.add(itr()); X X // now remove elements from the difference X listIterator litr(difference); X X for (litr.init(); ! litr; ++litr) X set.remove(litr()); X} X X X X//---------------------------------------------------------------------- X// class setList implementation X//---------------------------------------------------------------------- X Xtemplate void setList::add(T val) X{ X // only add if it is not already in the set X if (! includes(val)) X list::add(val); X} X X X Xtemplate void setList::remove(T val) X{ X listIterator itr(*this); X X for (itr.init(); ! itr; ++itr) X if (itr() == val) X { X itr.removeCurrent(); X return; X } X} X X X Xtemplate void setList::unionWith(setList & right) X{ X // simply make an iterator and then use the generic method X listIterator itr(right); X setUnionWith(*this, itr); X} X X X Xtemplate void setList::intersectWith(setList & right) X{ X // simply make an iterator and then use the generic method X listIterator itr(right); X setIntersectWith(*this, itr); X} X X X Xtemplate void setList::differenceFrom(setList & right) X{ X // simply make an iterator and then use the generic method X listIterator itr(right); X setDifferenceFrom(*this, itr); X} X X X Xtemplate int setList::subset(setList & right) X{ X // simply make an iterator and then use the generic method X listIterator itr(right); X return setSubset(*this, itr); X} X X X Xtemplate int operator == (setList & left, setList & right) X{ X // two sets are equal if both are subsets of each other X return left.subset(right) && right.subset(left); X} X X X X//---------------------------------------------------------------------- X// class setTable implementation X//---------------------------------------------------------------------- X Xtemplate setTable:: X setTable(unsigned int max, unsigned int (*f)(const T &)) X : hashTable, T, T>(max, f) X{ X // no further initialization X} X X X Xtemplate void setTable::add(T val) X{ X // compute bucket, then add element X buckets[hash(val)].add(val); X} X X X Xtemplate void setTable::differenceFrom(setTable & right) X{ X assert(tablesize == right.tablesize); X X // form the difference of each bucket independently X for (int i = 0; i < tablesize; i++) X buckets[i].differenceFrom(right.buckets[i]); X} X X X Xtemplate int setTable::includes(T val) const X{ X // compute bucket, then see if it includes element X return buckets[hash(val)].includes(val); X} X X X Xtemplate void setTable::intersectWith(setTable & right) X{ X assert(tablesize == right.tablesize); X X // form the intersection of each bucket independently X for (int i = 0; i < tablesize; i++) X buckets[i].intersectWith(right.buckets[i]); X} X X X Xtemplate void setTable::remove(T val) X{ X // compute bucket, then remove element X buckets[hash(val)].remove(val); X} X X X Xtemplate void setTable::unionWith(setTable & right) X{ X assert(tablesize == right.tablesize); X X // form the union of each bucket independently X for (int i = 0; i < tablesize; i++) X buckets[i].unionWith(right.buckets[i]); X} X X X Xtemplate int setTable::subset(setTable & right) const X{ X assert(tablesize == right.tablesize); X X // test subset of each bucket independently X for (int i = 0; i < tablesize; i++) X if (! buckets[i].subset(right.buckets[i])) X return 0; X X // all bucket subsets smaller than corresponding buckets X return 1; X} X X X Xtemplate iterator * setTable:: X makeIterator(unsigned int i) X{ X return new listIterator(buckets[i]); X} X X X X#endif END-of-set.h echo x - sim.h sed 's/^X//' >sim.h << 'END-of-sim.h' X//====================================================================== X// File: sim.h X// Author: Timothy A. Budd X// Description: This file contains the interface of the simulation X// classes. X// X// Copyright (c) 1992 by Timothy A. Budd. All Rights Reserved. X// may be reproduced for any non-commercial purpose X//====================================================================== X X#ifndef SIM_H X#define SIM_H X X#include X#include X X X X//---------------------------------------------------------------------- X// class event X// execution event in a discrete event driven X// simulation X//---------------------------------------------------------------------- X Xclass event X{ Xpublic: X // constructor uses time of event X event(unsigned int t); X X // time is a public data field X const int unsigned time; X X // execute event by invoking this method X virtual void processEvent() = 0; X}; X X X X//---------------------------------------------------------------------- X// class simulation X// framework for discrete event-driven simulations X//---------------------------------------------------------------------- X Xclass simulation X{ Xpublic: X // constructor X simulation(); X X // start and run simulation X void run(); X X // return current time X unsigned int currentTime(); X X // schedule a new future event X void scheduleEvent(event &); X X // flag to set when simulation is finished X int done; X Xprotected: X skewHeap eventQueue; X unsigned int time; X}; X X X X// Function Prototypes X Xint operator < (const event & left, const event & right); X X X X#endif END-of-sim.h echo x - split.h sed 's/^X//' >split.h << 'END-of-split.h' X//====================================================================== X// File: split.h X// Author: Timothy A. Budd X// Description: This file contains the interface to the split X// function, which splits a sentence string into words X// and returns a vector of these words. X// X// Copyright (c) 1992 by Timothy A. Budd. All Rights Reserved. X// may be reproduced for any non-commercial purpose X//====================================================================== X X#ifndef SPLIT_H X#define SPLIT_H X X X#include X#include X#include X X X// Function Prototype X Xvoid split(string &, const charSet &, vector &); X X X#endif END-of-split.h echo x - stack.h sed 's/^X//' >stack.h << 'END-of-stack.h' X//====================================================================== X// File: stack.h X// Author: Timothy A. Budd X// Description: This file contains the interface of the stack X// classes. X// X// Copyright (c) 1992 by Timothy A. Budd. All Rights Reserved. X// may be reproduced for any non-commercial purpose X//====================================================================== X X#ifndef STACK_H X#define STACK_H X X#include X#include X#include X#include X X//---------------------------------------------------------------------- X// class stack X// abstract class - simply defines protocol for X// stack operations X//---------------------------------------------------------------------- X Xtemplate class stack X{ Xpublic: X virtual void deleteAllValues() = 0; X virtual int isEmpty() const = 0; X virtual T pop() = 0; X virtual void push(T value) = 0; X virtual T top() const = 0; X}; X X X X//---------------------------------------------------------------------- X// class stackVector X// stack implemented using vector X// vector will grow as necessary to avoid overflow X//---------------------------------------------------------------------- X Xtemplate class stackVector : public stack X{ Xpublic: X // constructor requires a starting size X stackVector(unsigned int size); X stackVector(const stackVector & v); X X // stack operations X X virtual void deleteAllValues(); X virtual int isEmpty() const; X virtual T pop(); X virtual void push(T value); X virtual T top() const; X X // assignment X stackVector & operator = (const stackVector &); X Xprotected: X // data fields X vector data; X unsigned int nextSlot; X}; X X X X//---------------------------------------------------------------------- X// class stackList X// stack implemented using list operations X//---------------------------------------------------------------------- X Xtemplate class stackList : public stack X{ Xpublic: X // constructors X stackList(); X stackList(const stackList & v); X X // stack operations X virtual void deleteAllValues(); X virtual int isEmpty() const; X virtual T pop(); X virtual void push(T value); X virtual T top() const; X Xprotected: X // data fields X list data; X}; X X//---------------------------------------------------------------------- X// class stackVector implementation X//---------------------------------------------------------------------- X Xtemplate stackVector::stackVector(unsigned int size) X : data(size) X{ X // create and initialize a stack based on vectors X // make sure stack is initially empty X deleteAllValues(); X} X X X Xtemplate stackVector::stackVector(const stackVector & v) X : data(v.data), nextSlot(v.nextSlot) X{ X // no further initialization X} X X X Xtemplate void stackVector::deleteAllValues() X{ X // clear all elements from stack, by setting X // index to bottom of stack X nextSlot = 0; X} X X X Xtemplate int stackVector::isEmpty() const X{ X // return true if stack is empty X // if nextSlot points to bottom of stack X // then there are no elements X return nextSlot == 0; X} X X X Xtemplate T stackVector::pop() X{ X // return and remove the topmost element in the stack X assert(!isEmpty()); X return data[--nextSlot]; X} X X X Xtemplate void stackVector::push(T val) X{ X // push new value onto stack X // if stack is too small, then increase the size X if (nextSlot >= data.length()) X data.setSize(data.length() + 5); X X data[nextSlot++] = val; X} X X X Xtemplate T stackVector::top() const X{ X // return the topmost element in the stack X assert(!isEmpty()); X return data[nextSlot - 1]; X} X X X Xtemplate stackVector & stackVector::operator = X (const stackVector & right) X{ X data = right.data; X nextSlot = right.nextSlot; X return *this; X} X X X X//---------------------------------------------------------------------- X// class stackList implementation X//---------------------------------------------------------------------- X Xtemplate stackList::stackList() X{ X // create and initialize a stack based on lists X // make sure stack is initially empty X deleteAllValues(); X} X X X Xtemplate stackList::stackList(const stackList & v) X{ X // !!!WARNING: BUG!!! X data.deleteAllValues(); X} X X X Xtemplate void stackList::deleteAllValues() X{ X // clear all elements from stack, by setting X // delete all values from list X data.deleteAllValues(); X} X X X Xtemplate int stackList::isEmpty() const X{ X // return true if stack is empty X return data.isEmpty(); X} X X X Xtemplate T stackList::pop() X{ X // return and remove the topmost element in the stack X // get first element in list X T result = data.firstElement(); X X // remove element from list X data.removeFirst(); X X // return value X return result; X} X X X Xtemplate void stackList::push(T val) X{ X // push new value onto stack X data.add(val); X} X X X Xtemplate T stackList::top() const X{ X return data.firstElement(); X} X X X X#endif END-of-stack.h echo x - table.h sed 's/^X//' >table.h << 'END-of-table.h' X//====================================================================== X// File: table.h X// Author: Timothy A. Budd X// Description: This file contains the interface and implementation X// of the dictionary and table template classes. X// X// Copyright (c) 1992 by Timothy A. Budd. All Rights Reserved. X// may be reproduced for any non-commercial purpose X//====================================================================== X X#ifndef TABLE_H X#define TABLE_H X X#include X#include X#include X#include X X// X// in trying to get this to work with g++ it appears some X// template functions must be given in the class description X// I don't understand why. X X X//---------------------------------------------------------------------- X// class association X// A single key/value pair, X// usually maintained in a dictionary X//---------------------------------------------------------------------- X Xtemplate class association X{ Xpublic: X // value field is publically accessible X V valueField; X X // constructor X association(K initialKey, V initialValue); X association(const association & x); X X // assignment can be either to association or value X V operator =(association & anAssociation); X V operator =(V val); X X // accessor methods for key and value X K key() const; X V value() const; X Xprotected: X friend int operator == (association & l, association & r); X friend int operator == (association & l, K r); X X // key field cannot be altered X const K keyField; X X}; X X X//---------------------------------------------------------------------- X// class cAssociation X// a form of association that allows elements to be compared X//---------------------------------------------------------------------- X Xtemplate class cAssociation X : public association X{ Xpublic: X // constructor X cAssociation(K initialKey, V initialValue); X X friend int operator == (cAssociation & l, cAssociation & r); X friend int operator == (cAssociation & l, K & r); X X friend int operator < (cAssociation & l, cAssociation & r); X friend int operator < (cAssociation & l, K & r); X}; X X//---------------------------------------------------------------------- X// class dictionary X// A collection of key/value pairs X// implemented as a list of associations X//---------------------------------------------------------------------- X Xtemplate class dictionaryIterator; Xtemplate class table; X Xtemplate class dictionary X{ Xpublic: X // constructors X dictionary(); X dictionary(V initialValue); X dictionary(const dictionary & v); X X // find association with given key X association * associatedWith(K); X X // dictionary protocol X V & operator [](K key); X void deleteAllValues(); X int includesKey(K key); X int isEmpty() const; X void removeKey(K key); X void setInitial(V initialValue); X Xpublic: X // data is maintained in a list of associations X list *> data; X V initialValue; X X // friends X friend class dictionaryIterator; X friend class table; X}; X X//---------------------------------------------------------------------- X// class table X// dictionary collection of key/value pairs X// implemented using hash tables X//---------------------------------------------------------------------- X Xtemplate class table X : public hashTable, K, association *> X{ Xpublic: X // constructors X table(unsigned int max, unsigned int (*f)(const K &)); X table(unsigned int max, unsigned int (*f)(const K &), V &); X X // new table operators X V & operator [](K key); X void removeKey(K key); X void setInitial(V initialValue); X Xprotected: X iterator *> * makeIterator(unsigned int i); X}; X X//---------------------------------------------------------------------- X// class tableIterator X// iterator protocol for tables X//---------------------------------------------------------------------- X Xtemplate class tableIterator X : public hashTableIterator, K, association *> X{ Xpublic: X // constructor X tableIterator(table & v); X}; X X X X//---------------------------------------------------------------------- X// class orderedDictionary X// A ordered collection of key/value pairs X// implemented as a list of associations X//---------------------------------------------------------------------- X Xtemplate class orderedDictionaryIterator; X Xtemplate class orderedDictionary X{ Xpublic: X // constructors X X orderedDictionary(); X orderedDictionary(V initialValue); X orderedDictionary(orderedDictionary & v); X X // dictionary protocol X V & operator [](K key); X void deleteAllValues(); X int includesKey(K key); X int isEmpty() const; X void removeKey(K key); X void setInitial(V initialValue); X Xprivate: X // data is maintained in a list of associations X orderedList &> data; X V initialValue; X X // friends X friend class orderedDictionaryIterator; X friend class table; X X // find association with given key X cAssociation * associatedWith (K key); X}; X X X X//---------------------------------------------------------------------- X// class dictionaryIterator X// implementation of iterator protocol for dictionaries X//---------------------------------------------------------------------- X Xtemplate class dictionaryIterator X : public listIterator *> X{ Xpublic: X // constructor X dictionaryIterator(dictionary & dict); X}; X X X X//---------------------------------------------------------------------- X// class orderedDictionaryIterator X// implementation of iterator protocol for X// ordered dictionaries X//---------------------------------------------------------------------- X Xtemplate class orderedDictionaryIterator X : public listIterator &> X{ Xpublic: X // constructor X orderedDictionaryIterator(orderedDictionary & dict); X}; X X X X//---------------------------------------------------------------------- X// class sparseMatrix X// two dimensional matrix using dictionaries to store rows X//---------------------------------------------------------------------- X Xtemplate class sparseMatrix X{ Xpublic: X // constructors X sparseMatrix(unsigned int n, unsigned int m); X sparseMatrix(unsigned int n, unsigned int m, T initial); X X // only operation is subscript X dictionary & operator [](unsigned int n); X Xprivate: X vector< dictionary > data; X}; X X X X//---------------------------------------------------------------------- X// class sparseMatrix2 X// second form of sparse matrix, X// uses dictionaries for both rows and columns X//---------------------------------------------------------------------- X Xtemplate class sparseMatrix2 X{ Xpublic: X // constructors X sparseMatrix2(unsigned int n, unsigned int m) {} X sparseMatrix2(unsigned int n, unsigned int m, T init); X X dictionary & operator [] (unsigned int n); X Xprivate: X // data areas X T initialValue; X dictionary< int, dictionary > data; X}; X X X X//---------------------------------------------------------------------- X// class association implementation X//---------------------------------------------------------------------- X Xtemplate association:: X association(K initialKey, V initialValue) X : keyField(initialKey), valueField(initialValue) X{ X // no further initialization X} X Xtemplate association:: X association(const association & x) X : keyField(x.keyField), valueField(x.valueField) X{ X // no further initialization X} X Xtemplate V association:: X operator = (association & anAssociation) X{ X // assignment from an association X valueField = anAssociation.valueField; X return valueField; X} X X X X Xtemplate V association:: X operator = (V val) X{ X // assignment from a value X valueField = val; X return valueField; X} X X X Xtemplate K association::key() const X{ X // return key X return keyField; X} X Xtemplate V association::value() const X{ X // return value X return valueField; X} X X X Xtemplate int operator == X (association & left, association & right) X{ X // compare the key values for two associations X return left.key() == right.key(); X} X X X Xtemplate int operator == X (association & left, K rightKey) X{ X // compare the key values for two associations X return left.key() == rightKey; X} X X X X//---------------------------------------------------------------------- X// class dictionary implementation X//---------------------------------------------------------------------- X Xtemplate dictionary::dictionary() X{ X // nothing to initialize X} X X X Xtemplate dictionary::dictionary(V val) X{ X // set initial value X initialValue = val; X} X X X Xtemplate dictionary:: X dictionary(const dictionary & v) X : data(v.data), initialValue (v.initialValue) X{ X# if 0 X// GNU COMPLAINS ABOUT THIS X data = *v.data.duplicate(); X initialValue = v.initialValue; X# endif X} X Xtemplate association * dictionary:: X associatedWith(K key) X{ X // return the association with the given key X // or the null pointer if no association yet exists X listIterator *> itr(data); X X // loop over the elements, looking for a match X for (itr.init(); ! itr; ++itr) X if (itr()->key() == key) X { X // address of a reference is a pointer X return itr(); X } X X // not found, return null pointer X return 0; X} X X X Xtemplate V & dictionary::operator [] (K key) X{ X // return value of association specified by key X // first look to see if association is there already X association * newassoc = associatedWith(key); X X // if not there, make a new one X if (!newassoc) X { X newassoc = new association(key, initialValue); X assert(newassoc != 0); X data.add(newassoc); X } X X // return reference to value field X return newassoc->valueField; X} X X X Xtemplate void dictionary::deleteAllValues() X{ X data.deleteAllValues(); X} X X X Xtemplate int dictionary::includesKey(K key) X{ X // if there is an association, then element is in the dictionary X return associatedWith(key) != 0; X} X X X Xtemplate int dictionary::isEmpty() const X{ X return data.isEmpty(); X} X X X Xtemplate void dictionary::removeKey(K key) X{ X // loop over the elements looking for key X listIterator *> itr(data); X X for (itr.init(); ! itr; ++itr) X if (itr()->key() == key) X itr.removeCurrent(); X} X X X Xtemplate void dictionary::setInitial(V val) X{ X initialValue = val; X} X X X X X X//---------------------------------------------------------------------- X// class orderedDictionary implementation X//---------------------------------------------------------------------- X Xtemplate orderedDictionary::orderedDictionary() X{ X // nothing to initialize X} X X X Xtemplate orderedDictionary:: X orderedDictionary(V val) X{ X // set initial value X initialValue = val; X} X X X Xtemplate orderedDictionary:: X orderedDictionary(orderedDictionary & v) X{ X initialValue = v.initialValue; X X data.deleteAllValues(); X listIterator &> itr(v.data); X X for (itr.init(); !itr; ++itr) X data.add(itr()); X} X X X Xtemplate V & orderedDictionary:: X operator [] (K key) X{ X // return value of association specified by key X // first look to see if association is there already X cAssociation * newassoc = associatedWith(key); X X // if not there, make a new one X if (!newassoc) X { X newassoc = new cAssociation(key, initialValue); X assert(newassoc != 0); X data.add(*newassoc); X } X X // return reference to value field X return newassoc->valueField; X} X X X Xtemplate void orderedDictionary::deleteAllValues() X{ X data.deleteAllValues(); X} X X X Xtemplate int orderedDictionary::includesKey(K key) X{ X // if there is an association, then element is in the dictionary X return associatedWith(key) != 0; X} X X X Xtemplate int orderedDictionary::isEmpty() const X{ X return data.isEmpty(); X} X X X Xtemplate void orderedDictionary::removeKey(K key) X{ X // loop over the elements looking for key X listIterator &> itr(data); X X for (itr.init(); ! itr; ++itr) X if (itr().key() == key) X itr.removeCurrent(); X} X X X Xtemplate void orderedDictionary::setInitial(V val) X{ X initialValue = val; X} X X X Xtemplate cAssociation * orderedDictionary:: X associatedWith(K key) X{ X // return the association with the given key X // or the null pointer if no association yet exists X listIterator &> itr(data); X X // loop over the elements, looking for a match X for (itr.init(); ! itr; ++itr) X if (itr().key() == key) X { X // address of a reference is a pointer X cAssociation & theAssociation = itr(); X return &theAssociation; X } X X // not found, return null pointer X return 0; X} X X X X//---------------------------------------------------------------------- X// class dictionaryIterator implementation X//---------------------------------------------------------------------- X Xtemplate dictionaryIterator:: X dictionaryIterator(dictionary & dict) X : listIterator *>(dict.data) X{ X // no further initialization X} X X X X//---------------------------------------------------------------------- X// class orderedDictionaryIterator implementation X//---------------------------------------------------------------------- X Xtemplate orderedDictionaryIterator:: X orderedDictionaryIterator(orderedDictionary & dict) X : listIterator &>(dict.data) X{ X // no further initialization X} X X X X//---------------------------------------------------------------------- X// class sparseMatrix implementation X//---------------------------------------------------------------------- X Xtemplate sparseMatrix:: X sparseMatrix(unsigned int n, unsigned int m) X : data(n) X{ X // no further initialization X} X X X Xtemplate sparseMatrix:: X sparseMatrix(unsigned int n, unsigned int m, T initial) X : data(n) X{ X // set the initial value for each dictionary X for (unsigned int i = 0; i < n; i++) X data[i].setInitial(initial); X} X X X Xtemplate dictionary & sparseMatrix X ::operator [](unsigned int n) X{ X // simply return the appropriate dictionary X return data[n]; X} X X X X//---------------------------------------------------------------------- X// class sparseMatrix2 implementation X//---------------------------------------------------------------------- X Xtemplate sparseMatrix2:: X sparseMatrix2(unsigned int n, unsigned int m) X : data(n) X{ X // no further initialization X} X X X Xtemplate sparseMatrix2:: X sparseMatrix2(unsigned int n, unsigned int m, T initial) X : data(n) X{ X // set the initial value for each dictionary X for (unsigned int i = 0; i < n; i++) X data[i].setInitial(initial); X} X X X Xtemplate dictionary & sparseMatrix2:: X operator [] (unsigned int n) X{ X // subscript operator for sparse matrices X // if we already have a row, just return it X if (data.includesKey(n)) X return data[n]; X X // else make a new entry and set initial value X data[n].setInitial(initialValue); X return data[n]; X} X X X X//---------------------------------------------------------------------- X// class cAssociation implementation X//---------------------------------------------------------------------- X Xtemplate cAssociation::cAssociation(K n, V m) X : association(n, m) X{ X // no further initialization X} X X X Xtemplate X int operator == (cAssociation & left, cAssociation & right) X{ X // compare the key values for two associations X return left.key() == right.key(); X} X X X Xtemplate X int operator == (cAssociation & left, K & rightKey) X{ X // compare the key values for two associations X return left.key() == rightKey; X} X X X Xtemplate X int operator < (cAssociation & left, cAssociation & right) X{ X // compare the key values for two associations X return left.key() < right.key(); X} X X X Xtemplate X int operator < (cAssociation & left, K & rightKey) X{ X // compare the key value of an associations to a key value X return left.key() < rightKey; X} X X X X//---------------------------------------------------------------------- X// class table implementation X//---------------------------------------------------------------------- X Xtemplate table:: X table(unsigned int max, unsigned int (*f)(const K &)) X : hashTable, K, association *>(max, f) X{ X // no further initialization X} X X X Xtemplate table:: X table(unsigned int max, unsigned int (*f)(const K &), V & v) X : hashTable, K, association *>(max, f) X{ X // set the initial value in each bucket X setInitial(v); X} X X X Xtemplate V & table::operator [](K key) X{ X // find right dictionary, then subscript dictionary X return buckets[hash(key)][key]; X} X X X Xtemplate void table::removeKey(K key) X{ X // find the right bucket, then remove the key X buckets[hash(key)].removeKey(key); X} X X X Xtemplate void table::setInitial(V val) X{ X // set the initial value in each bucket X for (int i = 0; i < tablesize; i++) X buckets[i].initialValue = val; X} X X X Xtemplate iterator *> * table:: X makeIterator(unsigned int i) X{ X return new dictionaryIterator(buckets[i]); X} X X X X//---------------------------------------------------------------------- X// class tableIterator implementation X//---------------------------------------------------------------------- X Xtemplate tableIterator:: X tableIterator(table & v) X : hashTableIterator, K, association *>(v) X{ X // no further initialization X} X X X X#endif END-of-table.h echo x - tree.h sed 's/^X//' >tree.h << 'END-of-tree.h' X//====================================================================== X// File: tree.h X// Author: Timothy A. Budd X// Description: This file contains the interface of the tree X// classes. X// X// Copyright (c) 1992 by Timothy A. Budd. All Rights Reserved. X// may be reproduced for any non-commercial purpose X//====================================================================== X X#ifndef TREE_H X#define TREE_H X X# include X# include X# include X# include X# include X X X X//---------------------------------------------------------------------- X// class node X// a single node from a binary tree X//---------------------------------------------------------------------- X Xtemplate class node X{ Xpublic: X // constructors X node (T value); X node (T value, node * left, node * right); X X // public data area for value field X T value; X X // duplicate tree rooted at this node X virtual node * copy() const; X X // release entire tree at this node X void release(); X X // accessing, changing child nodes X node * left() const; X void left(node * l); X X node * right() const; X void right(node * r); X X // data areas X node * leftptr; X node * rightptr; X}; X X X X//---------------------------------------------------------------------- X// class searchTree X// collection designed for fast insertion, test, and X// removal operations X//---------------------------------------------------------------------- X Xtemplate class searchTreeIterator; X Xtemplate class searchTree X{ Xpublic: X // constructor X searchTree(); X searchTree(searchTree &); X virtual ~searchTree(); X X // protocol for search trees X virtual void add(T value); X void deleteAllValues(); X int includes(T value) const; X int isEmpty() const; X virtual void remove(T value); X Xprotected: X // data areas X node * root; X X friend class searchTreeIterator; X X // method used internally to delete top node X node * removeTop(node *); X}; X X X//---------------------------------------------------------------------- X// class inorderTreeTraversal X// perform an inorder traversal of a binary tree X//---------------------------------------------------------------------- X Xtemplate class inorderTreeTraversal : public iterator X{ Xpublic: X // constructor X inorderTreeTraversal(node * initialRoot); X inorderTreeTraversal(const inorderTreeTraversal & x); X inorderTreeTraversal() : itrstack(32) { } X X // reimplement iterator protocol X virtual int init(); X virtual int operator !(); X virtual T operator ()(); X virtual void operator =(T val); X virtual int operator ++(); X X // also permit changing the root X void setRoot(node * newRoot); X Xprivate: X // data ares X node * root; X //stackList *> itrstack; X stackVector *> itrstack; X X // internal method to slide down left subtree X void slideLeft(node *); X}; X X X X//---------------------------------------------------------------------- X// class searchTreeIterator X// iterator for search trees X//---------------------------------------------------------------------- X Xtemplate class searchTreeIterator X : public inorderTreeTraversal X{ Xpublic: X // constructor X searchTreeIterator(searchTree & tree); X X // initialize iteration, find first element X virtual int init(); X Xprivate: X // store reference to the entire tree X searchTree & base; X}; X X X X//---------------------------------------------------------------------- X// class avlNode X// a single node in an avl tree X//---------------------------------------------------------------------- X Xtemplate class avlNode : public node X{ Xpublic: X // constructor X avlNode(T value); X avlNode(T, node *, node *); X X // redefine access to left and right children X void left(avlNode * v); X avlNode * left() const; X void right(avlNode * v); X avlNode * right() const; X X // insert a new node into tree X avlNode * add(T value); X X // remove an item from tree, setting reference to containing node X avlNode * remove(T, avlNode * &); X X // duplicate tree X virtual node * copy() const; X Xprivate: X short balFac; // balance factor, either -1, 0 or 1 X X avlNode * singleRotateLeft(); X avlNode * singleRotateRight(); X avlNode * restoreLeftBalance(int); X avlNode * restoreRightBalance(int); X avlNode * balance(); X avlNode * removeLeftmostDescendent(avlNode * &); X}; X X X X//---------------------------------------------------------------------- X// class avlTree X// a form of binary search tree that maintains X// the height balance property X// thus ensuring efficient operation X//---------------------------------------------------------------------- X Xtemplate class avlTree : public searchTree X{ Xpublic: X // insertion procedure X virtual void add(T value); X X // removal procedure X virtual void remove(T value); X Xprivate: X avlNode * rootptr(); X}; X X X X//---------------------------------------------------------------------- X// class postorderTreeTraversal X// perform a post order traversal of a binary tree X//---------------------------------------------------------------------- X Xtemplate class postorderTreeTraversal : public iterator X{ Xpublic: X // constructor X postorderTreeTraversal(node * root); X postorderTreeTraversal(const postorderTreeTraversal & x); X X // reimplement iterator protocol X virtual int init(); X virtual int operator !(); X virtual T operator ()(); X virtual void operator =(T val); X virtual int operator ++(); X X // also permit changing the root X void setRoot(node * root); X Xprivate: X // data areas X node * root; X stackList *> itrstack; X X // internal method used to stack children of a node X void stackChildren(node *); X}; X X X X//---------------------------------------------------------------------- X// class preorderTreeTraversal X// perform a preorder traversal of a binary tree X//---------------------------------------------------------------------- X Xtemplate class preorderTreeTraversal : public iterator X{ Xpublic: X // constructor X preorderTreeTraversal(node * root); X preorderTreeTraversal(const preorderTreeTraversal &); X X // iterator protocol X virtual int init(); X virtual int operator !(); X virtual T operator ()(); X virtual void operator =(T val); X virtual int operator ++(); X X // in addition, permit user to set new root X void setRoot(node * root); X Xprivate: X // data areas X node * root; X stackList *> itrstack; X}; X X//---------------------------------------------------------------------- X// class levelorderTreeTraversal X// perform a level order traversal of a binary tree X//---------------------------------------------------------------------- X X# include X Xtemplate class levelorderTreeTraversal : public iterator X{ Xpublic: X // constructor X levelorderTreeTraversal(node * root); X levelorderTreeTraversal(const levelorderTreeTraversal &); X X // reimplement iterator protocol X virtual int init(); X virtual int operator !(); X virtual T operator ()(); X virtual void operator =(T val); X virtual int operator ++(); X X // also permit changing the root X void setRoot(node * root); X Xprivate: X // data areas X node * root; X queueList< node *> itrqueue; X}; X X X X//---------------------------------------------------------------------- X// class node implementation X//---------------------------------------------------------------------- X Xtemplate node::node(T val) X : value(val), leftptr(0), rightptr(0) X{ X // no further initialization X} X X Xtemplate node::node(T val, node * l, node * r) X : value(val), leftptr(l), rightptr(r) X{ X // no further initialization X} X X Xtemplate node * node::copy() const X{ X // return copy of tree rooted at node X node * newLeft; X node * newRight; X X // duplicate left child X if (leftptr != 0) X newLeft = leftptr->copy(); X else X newLeft = 0; X X // duplicate right child X if (rightptr != 0) X newRight = rightptr->copy(); X else X newRight = 0; X X // duplicate node, check that allocation worked X node * newptr = new node(value, newLeft, newRight); X assert(newptr != 0); X X // return new node X return newptr; X} X X Xtemplate void node::release() X{ X // release memory associated with children X if (leftptr) X { X // release left child X leftptr->release(); X delete leftptr; X leftptr = 0; X } X X if (rightptr) X { X // release right child X rightptr->release(); X delete rightptr; X rightptr = 0; X } X} X X Xtemplate node * node::left() const X{ X // return the left node X return leftptr; X} X X Xtemplate void node::left(node * l) X{ X // set the left node X leftptr = l; X} X X Xtemplate node * node::right() const X{ X // return the right node X return rightptr; X} X X Xtemplate void node::right(node * r) X{ X // set the right node X rightptr = r; X} X X X X//---------------------------------------------------------------------- X// class searchTree implementation X//---------------------------------------------------------------------- X Xtemplate searchTree::searchTree() X{ X // initialize tree X root = 0; X} X X X Xtemplate searchTree::searchTree(searchTree & v) X{ X // initialize tree by adding all the elements from argument X searchTreeIterator itr(v); X X root = 0; X X for (itr.init(); !itr; itr++) X add(itr()); X} X X X Xtemplate searchTree::~searchTree() X{ X // deallocate tree X if (root) X root->release(); X} X X X Xtemplate void searchTree::add(T val) X{ X // add value to binary search tree X if (root) X { X node * current = root; X node * child; X X while (current) X { X if (current->value < val) X { X // add to right subtree X child = current->right(); X X if (!child) X { X current->right(new node(val)); X return; X } X } X else X { X // add to left subtree X child = current->left(); X X if (!child) X { X current->left(new node(val)); X return; X } X } X X current = child; X } X } X else X root = new node(val); X} X X X Xtemplate void searchTree::deleteAllValues() X{ X // remove all values from tree X if (root != 0) X { X root->release(); X delete root; X root = 0; X } X} X X X Xtemplate int searchTree::includes(T val) const X{ X // see if argument value occurs in tree X if (root) X { X node * current = root; X X while (current) X { X if (current->value == val) X return 1; X X if (current->value < val) X current = current->right(); X else X current = current->left(); X } X } X X // not found X return 0; X} X X X Xtemplate int searchTree::isEmpty() const X{ X return root == 0; X} X X X Xtemplate void searchTree::remove(T val) X{ X // remove value from a binary search tree X // no root, just quit X if (!root) X return; X X // deleting root X if (root->value == val) X { X node * newroot = removeTop(root); X delete root; X root = newroot; X return; X } X X // otherwise some other node X node * parent = root; X X while (parent != 0) X { X node * child; X X if (parent->value < val) X { X // search right subtree X child = parent->right(); X X if (child && (child->value == val)) X { X parent->right(removeTop(child)); X delete child; X child = 0; X } X } X else X { X // search left subtree X child = parent->left(); X X if (child && (child->value == val)) X { X parent->left(removeTop(child)); X delete child; X child = 0; X } X } X X parent = child; X } X} X X X Xtemplate node * searchTree::removeTop(node * topNode) X{ X // remove topmost node from a binary search tree X node * left = topNode->left(); X node * right = topNode->right(); X X // case 1, no left node X if (left == 0) X return right; X X // case 2, no right node X if (right == 0) X return left; X X // case 3, right node has no left node X node * n = right->left(); X X if (n == 0) X { X right->left(left); X return right; X } X X // case 4, slide down left tree X node * parent = right; X X while (n->left() != 0) X { X parent = n; X n = n->left(); X } X X // now parent point to n, n has no left child X // disconnect and move to top X parent->left(n->right()); X n->left(left); X n->right(right); X return n; X} X X X X//---------------------------------------------------------------------- X// class searchTreeIterator implementation X//---------------------------------------------------------------------- X Xtemplate searchTreeIterator:: X searchTreeIterator(searchTree & t) X : inorderTreeTraversal(t.root), base(t) X{ X // no further initialization X} X X X Xtemplate int searchTreeIterator::init() X{ X // first set root for the iterator X setRoot(base.root); X X // then do inorder iterator initialization X return inorderTreeTraversal::init(); X} X X X X//---------------------------------------------------------------------- X// class avlNode implementation X//---------------------------------------------------------------------- X Xtemplate avlNode::avlNode(T value) X : node(value) X{ X balFac = 0; X} X X Xtemplate avlNode:: X avlNode(T value, node * left, node * right) X : node(value, left, right) X{ X balFac = 0; X} X Xtemplate void avlNode::left(avlNode * v) X{ X node::left(v); X} X X X Xtemplate avlNode * avlNode::left() const X{ X return (avlNode *) node::left(); X} X X X Xtemplate void avlNode::right(avlNode * v) X{ X node::right(v); X} X X X Xtemplate avlNode * avlNode::right() const X{ X return (avlNode *) node::right(); X} X X X Xtemplate avlNode * avlNode::add(T val) X{ X // add new element into balanced avl tree X if (val < value) X { X // insert into left subtree X if (left()) X { X int oldbf = left()->balFac; X left(left()->add(val)); X X // check to see if tree grew X if ((left()->balFac != oldbf) && left()->balFac) X balFac--; X } X else X { X left(new avlNode(val)); X X // 0 becomes -1, 1 becomes 0 X balFac--; X } X } X else X { X // insert into right subtree X if (right()) X { X int oldbf = right()->balFac; X right(right()->add(val)); X X // check to see if tree grew X if ((right()->balFac != oldbf) && right()->balFac) X balFac++; X } X else X { X right(new avlNode(val)); X X // 0 becomes 1, -1 becomes 0 X balFac++; X } X } X X // check if we are now out of balance, if so balance X if ((balFac < -1) || (balFac > 1)) X return balance(); X X return this; X} X X X Xtemplate avlNode * avlNode:: X remove(T val, avlNode * & junk) X{ X // remove indicated node, returning node in variable junk X if (val == value) X { X // we're it X junk = this; X X // if no right child, return left X if (!left()) X return right(); X if (!right()) X return left(); X X // else find and remove smallest left X // child of the right child X int oldbf = right()->balFac; X avlNode * newroot; X right(right()->removeLeftmostDescendent(newroot)); X X // connect new root X newroot->left(left()); X newroot->right(right()); X newroot->balFac = balFac; X return newroot->restoreRightBalance(oldbf); X } X else if (val < value) X { X // remove from left child X if (!left()) X return this; // no left child X X // do the deletion X int oldbf = left()->balFac; X left(left()->remove(val, junk)); X return restoreLeftBalance(oldbf); X } X else X { X // remove from right child X if (!right()) X return this; X X // do the deletion X int oldbf = right()->balFac; X right(right()->remove(val, junk)); X return restoreRightBalance(oldbf); X } X} X X X Xtemplate node * avlNode::copy() const X{ X // return copy of tree rooted at node X node * newLeft; X node * newRight; X X // duplicate left child X if (leftptr != 0) X newLeft = leftptr->copy(); X else X newLeft = 0; X X // duplicate right child X if (rightptr != 0) X newRight = rightptr->copy(); X else X newRight = 0; X X // duplicate node, check that allocation worked X avlNode * newptr = new avlNode(value, newLeft, newRight); X assert(newptr != 0); X newptr->balFac = balFac; X X // return new node X return newptr; X} X X X Xtemplate avlNode * avlNode::singleRotateLeft() X{ X // perform a single left rotation of the current node X avlNode * nodeA = this; X avlNode * nodeB = nodeA->right(); X X // make reconnections X nodeA->right(nodeB->left()); X nodeB->left(nodeA); X X // now update the balance factors X int Abf = nodeA->balFac; X int Bbf = nodeB->balFac; X X if (Bbf <= 0) X { X if (Abf >= 1) X nodeB->balFac = Bbf - 1; X else X nodeB->balFac = Abf + Bbf - 2; X X nodeA->balFac = Abf - 1; X } X else X { X if (Abf <= Bbf) X nodeB->balFac = Abf - 2; X else X nodeB->balFac = Bbf - 1; X X nodeA->balFac = (Abf - Bbf) - 1; X } X X return nodeB; X} X X X Xtemplate avlNode * avlNode::singleRotateRight() X{ X // make a single right rotation of current node X avlNode * nodeA = this; X avlNode * nodeB = nodeA->left(); X X // make reconnections X nodeA->left(nodeB->right()); X nodeB->right(nodeA); X X // now update the balance factors X int Abf = nodeA->balFac; X int Bbf = nodeB->balFac; X X if (Bbf <= 0) X { X if (Bbf > Abf) X nodeB->balFac = Bbf + 1; X else X nodeB->balFac = Abf + 2; X X nodeA->balFac = 1 + Abf - Bbf; X } X else X { X if (Abf <= -1) X nodeB->balFac = Bbf + 1; X else X nodeB->balFac = Abf + Bbf + 2; X X nodeA->balFac = 1 + Abf; X } X X return nodeB; X} X X X Xtemplate avlNode * avlNode::restoreLeftBalance(int oldbf) X{ X avlNode * leftchild = left(); X X // fix up our balance factors X if (!leftchild) X balFac++; X else if ((leftchild->balFac != oldbf) && (leftchild->balFac == 0)) X balFac++; X X // rebalance if necessary X if (balFac > 1) X return balance(); X X return this; X} X X X Xtemplate avlNode * avlNode::restoreRightBalance(int oldbf) X{ X avlNode * rightchild = right(); X X // fix up our balance factors X if (!rightchild) X balFac++; X else if ((rightchild->balFac != oldbf) && (rightchild->balFac == 0)) X balFac++; X X // rebalance if necessary X if (balFac > 1) X return balance(); X X return this; X} X X X Xtemplate avlNode * avlNode::balance() X{ X // balance tree rooted at node X // using single or double rotations as appropriate X if (balFac < 0) X { X if (left()->balFac <= 0) X { X // perform single rotation X return singleRotateRight(); X } X else X { X // perform double rotation X left(left()->singleRotateLeft()); X return singleRotateRight(); X } X } X else X { X if (right()->balFac >= 0) X return singleRotateLeft(); X else X { X // perform double rotation X right(right()->singleRotateRight()); X return singleRotateLeft(); X } X } X} X X X Xtemplate avlNode * avlNode::removeLeftmostDescendent X (avlNode * & childptr) X{ X // find and remove the leftmost descendent of a node X // first see if we are the left child X avlNode * leftchild = left(); X X if (! leftchild) X { X // we are X childptr = this; X return right(); // remove self X } X X // else save old bal factor of left child X int oldbf = leftchild->balFac; X X // do the deletion X left(leftchild->removeLeftmostDescendent(childptr)); X X // fix up our balance factors X return restoreLeftBalance(oldbf); X} X X X X//---------------------------------------------------------------------- X// class avlTree implementation X//---------------------------------------------------------------------- X Xtemplate void avlTree::add(T val) X{ X // add new value into balanced AVL tree X if (root) X root = rootptr()->add(val); X else X root = new avlNode(val); X} X X X Xtemplate void avlTree::remove(T val) X{ X // remove an element from an AVL Tree X avlNode * eliminatedNode = 0; X X if (root) X root = rootptr()->remove(val, eliminatedNode); X if (eliminatedNode) X delete eliminatedNode; X} X X X Xtemplate avlNode * avlTree::rootptr() X{ X return (avlNode *) root; X} X X X X//---------------------------------------------------------------------- X// class postorderTreeTraversal implementation X//---------------------------------------------------------------------- X Xtemplate postorderTreeTraversal:: X postorderTreeTraversal(node * r) X : root(r) X{ X // no further initialization X} X Xtemplate postorderTreeTraversal:: X postorderTreeTraversal(const postorderTreeTraversal & x) X : root(x.root) X{ X // no further initialization X} X Xtemplate int postorderTreeTraversal::init() X{ X // clear out the stack X itrstack.deleteAllValues(); X X // then initialize it X stackChildren(root); X return !itrstack.isEmpty(); X} X X X Xtemplate int postorderTreeTraversal::operator !() X{ X // we are done when stack is empty X return !itrstack.isEmpty(); X} X X X Xtemplate T postorderTreeTraversal::operator()() X{ X // return value of current node X node * n = itrstack.top(); X return n->value; X} X X X Xtemplate void postorderTreeTraversal::operator=(T val) X{ X // change the current value X node * n = itrstack.top(); X n->value = val; X} X X X Xtemplate int postorderTreeTraversal::operator ++() X{ X // move to the next item in sequence X // pop current node from stack X itrstack.pop(); X X // return false if stack is empty, and hence there are no more items X return !itrstack.isEmpty(); X} X X X Xtemplate void postorderTreeTraversal:: X setRoot(node * newRoot) X{ X // set new root X root = newRoot; X} X X X Xtemplate void postorderTreeTraversal:: X stackChildren(node * n) X{ X // stack all the children of the current node X itrstack.push(n); X node * next = n->right(); X X if (next) X stackChildren(next); X X next = n->left(); X X if (next) X stackChildren(next); X} X X X X//---------------------------------------------------------------------- X// class preorderTreeTraversal implementation X//---------------------------------------------------------------------- X Xtemplate preorderTreeTraversal:: X preorderTreeTraversal(node * r) X : root(r) X{ X // no further initialization X} X Xtemplate preorderTreeTraversal:: X preorderTreeTraversal(const preorderTreeTraversal & x) X : root(x.root) X{ X // no further initialization X} X Xtemplate int preorderTreeTraversal::init() X{ X // initialize a preorder traversal of a tree X // first initialize the stack X itrstack.deleteAllValues(); X X // first time out, just push the root X if (root != 0) X itrstack.push(root); X X return !itrstack.isEmpty(); X} X X X Xtemplate int preorderTreeTraversal::operator !() X{ X // we are done when stack is empty X return !itrstack.isEmpty(); X} X X X Xtemplate T preorderTreeTraversal::operator()() X{ X // return value of current node X node * n = itrstack.top(); X return n->value; X} X X X Xtemplate void preorderTreeTraversal::operator=(T val) X{ X // change the current value X node * n = itrstack.top(); X n->value = val; X} X X X Xtemplate int preorderTreeTraversal::operator ++() X{ X // inv - for each node on stack except top X // left children are being investigated X // for all including top no right children have been visited X node * current = itrstack.top(); X node * next = current->left(); X X if (next) X { X itrstack.push(next); X return 1; X } X X // no more left nodes, X // find unexplored right child X while (! itrstack.isEmpty()) X { X current = itrstack.pop(); X next = current->right(); X X if (next) X { X // note parent is not on stack, X // preserving invariant X itrstack.push(next); X return 1; X } X } X X return 0; X} X X X Xtemplate void preorderTreeTraversal:: X setRoot(node * newRoot) X{ X // set new root X root = newRoot; X} X X X X//---------------------------------------------------------------------- X// class inorderTreeTraversal implementation X//---------------------------------------------------------------------- X Xtemplate inorderTreeTraversal:: X inorderTreeTraversal(node * initialRoot) X : itrstack(32) X{ X root = initialRoot; X itrstack.deleteAllValues(); X} X Xtemplate inorderTreeTraversal:: X inorderTreeTraversal(const inorderTreeTraversal & x) X : itrstack(32), root(x.root) X{ X X} X Xtemplate int inorderTreeTraversal::init() X{ X // initialize inorder tree traversal X // clear out the stack X itrstack.deleteAllValues(); X X // then reinitialize it X slideLeft(root); X return !itrstack.isEmpty(); X} X X X Xtemplate int inorderTreeTraversal::operator !() X{ X // we are done when stack is empty X return !itrstack.isEmpty(); X} X X X Xtemplate T inorderTreeTraversal::operator()() X{ X // return value of current node X node * n = itrstack.top(); X return n->value; X} X X X Xtemplate void inorderTreeTraversal::operator=(T val) X{ X // change the current value X node * n = itrstack.top(); X n->value = val; X} X X X Xtemplate int inorderTreeTraversal::operator ++() X{ X // inv - for each node on stack, left children X // have been explored, right children have not X if (! itrstack.isEmpty()) X { X node * n = itrstack.pop(); X node * next = n->right(); X X if (next) X slideLeft(next); X } X X // if stack isn't empty we have nodes X return !itrstack.isEmpty(); X} X X X Xtemplate void inorderTreeTraversal:: X setRoot(node * newRoot) X{ X // set new root X root = newRoot; X} X X X Xtemplate void inorderTreeTraversal:: X slideLeft(node * current) X{ X // slide left from the current node X while (current) X { X itrstack.push(current); X current = current->left(); X } X} X X X X//---------------------------------------------------------------------- X// class levelorderTreeTraversal implementation X//---------------------------------------------------------------------- X Xtemplate levelorderTreeTraversal:: X levelorderTreeTraversal(node * r) X : root(r) X{ X // no further initialization X} X X Xtemplate levelorderTreeTraversal:: X levelorderTreeTraversal(const levelorderTreeTraversal & x) X : root(x.root), itrqueue(x.itrqueue) X{ X // no further initialization X} X Xtemplate int levelorderTreeTraversal::init() X{ X // initialize a preorder traversal of a tree X // first initialize the queue X itrqueue.deleteAllValues(); X X // first time out, just enqueue the root X if (root != 0) X itrqueue.enqueue(root); X X return !itrqueue.isEmpty(); X} X Xtemplate int levelorderTreeTraversal::operator !() X{ X // we are done when queue is empty X return !itrqueue.isEmpty(); X} X X X Xtemplate T levelorderTreeTraversal::operator()() X{ X // return value of current node X node * n = itrqueue.front(); X return n->value; X} X X X Xtemplate void levelorderTreeTraversal::operator=(T val) X{ X // change the current value X node * n = itrqueue.front(); X n->value = val; X} X X X Xtemplate int levelorderTreeTraversal::operator ++() X{ X // queue children of current node X if (!itrqueue.isEmpty()) X { X node * n = itrqueue.dequeue(); X node * next; X next = n->left(); X X if (next) X itrqueue.enqueue(next); X X next = n->right(); X X if (next) X itrqueue.enqueue(next); X } X X return !itrqueue.isEmpty(); X} X X X Xtemplate void levelorderTreeTraversal:: X setRoot(node * newRoot) X{ X // set new root X root = newRoot; X} X X X//---------------------------------------------------------------------- X// miscellaneous template functions X//---------------------------------------------------------------------- X X// preorder processing of tree rooted at current X Xtemplate void preorder(node * current) X{ X // visit node, left child, right child X if (current) X { X // process current node X process(current->value); X X // then visit children X preorder(current->left()); X preorder(current->right()); X } X} X X X X// inorder processing of tree rooted at current X Xtemplate void inorder(node * current) X{ X // visit left child, node, right child X if (current) X { X inorder(current->left()); X process(current->value); X inorder(current->right()); X } X} X X X X// postorder processing of tree rooted at current X Xtemplate void postorder(node * current) X{ X // visit left child, right child, node X if (current) X { X postorder(current->left()); X postorder(current->right()); X process(current->value); X } X} X X// X// g++ and cfront treat these differently X// X X# ifdef __GNUG__ X X# include X X# endif X X# ifndef __GNUG__ X Xtemplate void treeSort(vector & v); X X# endif X X#endif END-of-tree.h echo x - vector.h sed 's/^X//' >vector.h << 'END-of-vector.h' X//====================================================================== X// File: vector.h X// Author: Timothy A. Budd X// Description: This file contains the interface and implementation X// of the vector template classes. X// X// Copyright (c) 1992 by Timothy A. Budd. All Rights Reserved. X// may be reproduced for any non-commercial purpose X//====================================================================== X X#ifndef VECTOR_H X#define VECTOR_H X X X#include X#include X X X//---------------------------------------------------------------------- X// class vector X// type safe and access safe vector data type X// permits dynamic modification of vector length X//---------------------------------------------------------------------- X Xtemplate class vector X{ Xpublic: X // constructors and destructor X vector(unsigned int numberElements); X vector(unsigned int numberElements, T initialValue); X vector(const vector & source); X virtual ~vector(); X X // access to elements via subscript X T & operator [] (unsigned int index) const; X X // assignment X vector & operator = (const vector &); X X // length of vector X unsigned int length() const; X X // dynamically change size X unsigned int setSize(unsigned intnumberOfElements); X unsigned int setSize(unsigned intnumberOfElements, X T initialValue); X Xprotected: X // data areas X T * data; X unsigned int size; X}; X X X X//---------------------------------------------------------------------- X// class boundedVector X// vectors with explicit upper and lower bounds X//---------------------------------------------------------------------- X Xtemplate class boundedVector : public vector X{ Xpublic: X // constructors X boundedVector(int lowIndex, int highIndex); X boundedVector(int lowIndex, int highIndex, T & initialValue); X boundedVector(const boundedVector & source); X X // element access X T & operator [] (int index) const; X X // structural information X int lowerBound() const; X int upperBound() const; X Xprotected: X int lowbound; X}; X X X X//---------------------------------------------------------------------- X// class vectorIterator X// iterator protocol used to loop over vector elements X//---------------------------------------------------------------------- X Xtemplate class vectorIterator : public iterator X{ Xpublic: X // constructor X vectorIterator(vector &); X vectorIterator(const vectorIterator &); X X // iterator protocol X virtual int init(); X virtual T operator ()(); X virtual int operator !(); X virtual int operator ++(); X virtual void operator =(T newValue); X X // new methods specific to vector iterators X int operator --(); X int key(); X Xprotected: X // data fields X unsigned int currentKey; X vector & data; X}; X X// X// class orderedVector X// vector maintained in sorted order X// X Xtemplate class orderedVectorIterator; X Xtemplate class orderedVector { Xpublic: X // constructors X orderedVector(); X orderedVector(const orderedVector & v); X X // subscript operation X T & operator [ ] (unsigned int index) const; X X // protocol for searching X void add (T value); X void deleteAllValues (); X int includes (T value) const; X int isEmpty () const; X void remove (T value); X Xprivate: X // data area is vector for values X vector data; X X friend class orderedVectorIterator; X}; X Xtemplate Xclass orderedVectorIterator : public vectorIterator X{ Xpublic: X orderedVectorIterator(orderedVector &); X}; X Xtemplate inline XorderedVectorIterator::orderedVectorIterator(orderedVector & x) X : vectorIterator(x.data) X{ X // no further initialization X} X X X// X// class matrix X// two dimensional arrays X// X Xtemplate Xclass matrix { Xpublic: X matrix(unsigned int numberOfRows, unsigned int numberOfColumns); X matrix(unsigned int numberOfRows, unsigned int numberOfColumns, X T initialValue); X X ~matrix(); X X vector & operator [ ] (unsigned int index) const; X X int numberRows() const; X int numberColumns() const; X Xprivate: X vector *> rows; X}; X X// X// class enumVector X// vector abstraction index by X// elements of an enumerated type X// X Xtemplate Xclass enumVector : public vector { Xpublic: X // constructors X enumVector(E max); X enumVector(const enumVector & v); X X // operations X T & operator [ ] (E index); X}; X X//---------------------------------------------------------------------- X// class vector implementation X//---------------------------------------------------------------------- X Xtemplate vector::vector(unsigned int numberElements) X : size(numberElements) X{ X // create and initialize a new vector X // allocate the space for the elements X data = new T[size]; X X // check that allocation was successful X assert(data != 0); X} X X X Xtemplate vector::vector(unsigned int numberElements, X T initialValue) : size(numberElements) X{ X // create and initialize a new vector X // allocate the space for the elements X data = new T[size]; X assert(data != 0); X X // set each element to the initial value X for (int i = 0; i < size; i++) X data[i] = initialValue; X} X X X Xtemplate vector::vector(const vector & source) X : size(source.size) X{ X // create and initialize a new vector X // allocate the space for the elements X data = new T[size]; X assert(data != 0); X X // copy values from old vector X for (int i = 0; i < size; i++) X data[i] = source.data[i]; X} X X X Xtemplate vector::~vector() X{ X // free teh dynamic memory buffer X delete [] data; X data = 0; X} X X X Xtemplate T & vector::operator [] (unsigned int index) const X{ X // subscript a vector value X // check that index is valid X assert(index < size); X X // return requested element X return data[index]; X} X X X Xtemplate vector & vector::operator = X (const vector & right) X{ X // match sizes X if (size != right.size) X setSize(right.size); X X // copy the elements X for (int i = 0; i < right.size; i++) X data[i] = right.data[i]; X X // return current value X return *this; X} X X X Xtemplate unsigned int vector::length() const X{ X // return the number of elements in the vector X return size; X} X X Xtemplate unsigned int vector::setSize X (unsigned int numberOfElements) X{ X // dynamically alter the size of the vector X X // first create the new data area X T * newData = new T[numberOfElements]; X assert(newData != 0); X X if (numberOfElements <= size) X { X // data area is shrinking - copy as many elements as possible X for (int i = 0; i < numberOfElements; i++) X newData[i] = data[i]; X } X else X { X // data area is growing - first copy old values X for (int i = 0; i < size; i++) X newData[i] = data[i]; X } X X // delete the old data buffer X delete [] data; X X // update the data member fields X size = numberOfElements; X data = newData; X X // return new size X return size; X} X X X Xtemplate unsigned int vector::setSize X (unsigned int numberOfElements, T initialValue) X{ X // the following are for a g++ compiler bug X int i; X T * newData; X X // dynamically alter the size of the vector X X // first create the new data area X newData = new T[numberOfElements]; X assert(newData != 0); X X if (numberOfElements <= size) X { X // data area is shrinking - copy as many elements as possible X for (i = 0; i < numberOfElements; i++) { X newData[i] = data[i]; X } X } X else X { X // data area is growing - first copy old values X for (int i = 0; i < size; i++) { X newData[i] = data[i]; X } X X // then initialize new values X for (i = size; i < numberOfElements; i++) X newData[i] = initialValue; X } X X // delete the old data buffer X delete [] data; X X // update the data member fields X size = numberOfElements; X data = newData; X X // return new size X return size; X} X X X X//---------------------------------------------------------------------- X// class boundedVector implementation X//---------------------------------------------------------------------- X Xtemplate boundedVector::boundedVector X (int lowIndex, int highIndex) X : lowbound(lowIndex), vector(1 + highIndex - lowIndex) X{ X // create and initialize a new bounded vector X assert(lowIndex <= highIndex); X} X X X Xtemplate boundedVector::boundedVector X (int lowIndex, int highIndex, T & initialValue) X : lowbound(lowIndex), vector(1 + highIndex - lowIndex, initialValue) X{ X // create and initialize a new bounded vector X assert(lowIndex <= highIndex); X} X X X Xtemplate boundedVector::boundedVector X (const boundedVector & source) X : lowbound(source.lowbound), vector(source) X{ X // no further initialization necessary X} X X X Xtemplate T & boundedVector::operator [](int index) const X{ X // subscript operator for bounded vectors X // subtract off lower bound X // yielding value between 0 and size of vector X // then use subscript from parent class X return vector::operator [](index - lowbound); X} X X X Xtemplate int boundedVector::lowerBound() const X{ X // return smallest legal index for bounded vector X return lowbound; X} X X X Xtemplate int boundedVector::upperBound() const X{ X // return largest legal index for bounded vector X return lowerBound() + length() - 1; X} X X X X//---------------------------------------------------------------------- X// class vectorIterator implementation X//---------------------------------------------------------------------- X Xtemplate vectorIterator::vectorIterator(vector & v) X : data(v) X{ X // create and initialize a vector iterator X init(); X} X Xtemplate vectorIterator:: X vectorIterator(const vectorIterator & x) X : data(x.data), currentKey(x.currentKey) X{ X // no further initialization X} X X Xtemplate int vectorIterator::init() X{ X // set current key to firstelement X currentKey = 0; X return operator !(); X} X X X Xtemplate T vectorIterator::operator ()() X{ X // return current value X return data[currentKey]; X} X X X Xtemplate int vectorIterator::operator !() X{ X // return true if there is a current element X return currentKey < data.length(); X} X X X Xtemplate int vectorIterator::operator ++() X{ X // advance to the next element X currentKey++; X return operator !(); X} X X X Xtemplate void vectorIterator::operator = (T newValue) X{ X // change the current index value X data[currentKey] = newValue; X} X X X Xtemplate int vectorIterator::operator --() X{ X // move current key back one element X if (currentKey > 0) X currentKey--; X X return operator !(); X} X X X Xtemplate int vectorIterator::key() X{ X // return index of current value X return currentKey; X} X X//---------------------------------------------------------------------- X// class matrix implementation X//---------------------------------------------------------------------- X Xtemplate Xmatrix::matrix(unsigned int numberOfRows, unsigned int numberOfColumns) X : rows(numberOfRows) X{ X // create and initialize a new matrix value X // now allocate each row of data X for (unsigned int i = 0; i < numberOfRows; i++) { X rows[i] = new vector(numberOfColumns); X // check that allocation was successful X assert(rows[i] != 0); X } X} X Xtemplate Xmatrix::matrix(unsigned int numberOfRows, unsigned int numberOfColumns, X T initialValue) : rows(numberOfRows) X{ X // create and initialize a new matrix value X // now allocate each row of data X for (unsigned int i = 0; i < numberOfRows; i++) { X rows[i] = new vector(numberOfColumns, initialValue); X // check that allocation was successful X assert(rows[i] != 0); X } X} X Xtemplate Xmatrix::~matrix() X{ X // free up dynamic storage allocated by matrix object X unsigned int max = rows.length(); X for (unsigned int i = 0; i < max; i++) { X // some compilers do not allow X // subscripted variables in delete X //vector * p = rows[i]; X //delete p; X rows[i] = 0; X } X} X Xtemplate Xvector & matrix::operator [ ] (unsigned int index) const X{ // return elemement (vector) index by value X // check that reference is valid X assert(rows[index] != 0 ); X X // return vector value X return * rows[index]; X} X X Xtemplate Xint matrix::numberRows() const X{ X // return number of rows in vector X return rows.length(); X} X Xtemplate Xint matrix::numberColumns() const X{ X // return number of columns in vector X return rows[0]->length(); X} X X//---------------------------------------------------------------------- X// class enumVector implementation X//---------------------------------------------------------------------- X Xtemplate XenumVector::enumVector(E max) : vector(1 + int(max)) X{ X // create and initialize an instance of enumerated vector X} X Xtemplate XenumVector::enumVector(const enumVector & source) : vector(source) X{ X // create and initialize an instance of enumerated vector X} X Xtemplate XT & enumVector::operator [ ] (E index) X{ X // subscript an enumerated vector X // simply convert enumerated index value into integer X return vector::operator [ ] (int(index)); X} X X// ******************************************************* X// template functions X// Cfront demands these are in a different file, X// g++ and borland want them in this file. X// ******************************************************* X X# ifdef __GNUG__ X X# include X X# endif X X# ifndef __GNUG__ X Xtemplate Xint binarySearch(VecType data, EleType ele, unsigned int max); X Xtemplate void swap( vector & data, int i, int j); X Xtemplate void bubbleSort(vector & data); X Xtemplate void selectionSort(vector & data); X Xtemplate void insertionSort(vector & data); X Xtemplate Xint partition(vector & v, int low, int high, int pivotIndex); X Xtemplate XT findElement(vector & v, int N, int low, int high); X Xtemplate Xvoid quackSort(vector & v, int low, int high); X Xtemplate Xvoid quackSort(vector & v); X X# endif X X// X// implementation of ordered vectors X// X Xtemplate orderedVector::orderedVector() : data(0) X{ X // no further initialization required X} X Xtemplate XT & orderedVector::operator [ ] (unsigned int index) const X{ X return data[index]; X} X Xtemplate XorderedVector::orderedVector(const orderedVector & v) : data(v.data) X{ X // no further initialization required X} X Xtemplate void orderedVector::deleteAllValues() X{ // set the size of the vector to zero X // thereby deleting all values X data.setSize(0); X} X Xtemplate int orderedVector::isEmpty() const X{ // collection is empty if vector is length zero X return data.length() == 0; X} X Xtemplate void orderedVector::add(T value) X{ X // get the current length of the vector X unsigned int max = data.length(); X X // perform binary search to find proper location for element X unsigned int index = binarySearch(data, value, max); X X // grow vector to new size X data.setSize(max + 1); X X // move everything up to make space X for (unsigned int i = max; i > index; i--) X data[i] = data[i-1]; X X // place element in location X data[index] = value; X} X Xtemplate int orderedVector::includes(T value) const X{ // see if vector includes given element X unsigned int max = data.length(); X unsigned int index = binarySearch(data, value, max); X // if value is the right element, return 1 X if (index < max) X if (value == data[index]) X return 1; X // not found X return 0; X} X Xtemplate void orderedVector::remove(T value) X{ // remove a value from collection, if present X unsigned int max = data.length(); X unsigned int index = binarySearch(data, value, max); X // if value is the right element, return 1 X if (index < max) X if (value == data[index]) { X // found element, remove it X max = max - 1; X for (unsigned int i = index; i < max; i++) X data[i] = data[i+1]; X // then change the size of the vector X data.setSize(max); X } X} X X#endif END-of-vector.h echo x - vertex.h sed 's/^X//' >vertex.h << 'END-of-vertex.h' X//================================================================== X// File: vertex.h X// Author: Timothy A. Budd X// Platform: Cfront X// Description: Template Description of graph vertex X// Copyright (c) 1992 by Timothy A. Budd, All Rights Reserved X// Permission granted for duplication if not for profit X//================================================================== X X# ifndef vertexH X# define vertexH X X// X// class vertex X// a simple unweighted graph vertex X// X X# include X Xtemplate class vertex { Xpublic: X // data value is publically accessible X T value; X setList &> arcs; X X // constructor X vertex(); X vertex(T init); X X // add a new arc X void addArc(vertex &); X}; X Xtemplate Xint operator == (const vertex left, const vertex & right); X X# endif END-of-vertex.h echo x - bitvec.C sed 's/^X//' >bitvec.C << 'END-of-bitvec.C' X//====================================================================== X// File: bitvec.cpp X// Author: Timothy A. Budd X// Description: This file contains the implementation of the bit X// vector classes. X// X// Copyright (c) 1992 by Timothy A. Budd. All Rights Reserved. X// may be reproduced for any non-commercial purpose X//====================================================================== X X# include X# include X X//---------------------------------------------------------------------- X// class bitVector implementation X//---------------------------------------------------------------------- X XbitVector::bitVector(unsigned int numberOfElements) X : bitValues((numberOfElements + 7)/8, 0) X{ X // no additional initialization X} X X X X XbitVector::bitVector(const bitVector & source) X : bitValues(source.bitValues) X{ X // no additional initialization X} X X X Xunsigned int bitVector::length() const X{ X // eight bits stored in every vector element X return 8 * bitValues.length(); X} X X X Xvoid bitVector::set(unsigned int index) X{ X // set the indicated bit in the data array X bitValues[byteNumber(index)] |= mask(index); X} X X X Xvoid bitVector::clear(unsigned int index) X{ X // clear the indicated bit in the bitValues array X bitValues[byteNumber(index)] &= ~ mask(index); X} X X X Xint bitVector::test(unsigned int index) const X{ X // test the indicated bit in the bitValues array X return 0 != (bitValues[byteNumber(index)] & mask(index)); X} X X X Xvoid bitVector::flip(unsigned int index) X{ X // flip the indicated bit in the bitValues array X bitValues[byteNumber(index)] ^= mask(index); X} X X X Xunsigned int bitVector::byteNumber(unsigned int index) const X{ X // return index of byte containing specified value X // byte number is index value divided by 8 X return index >> 3; X} X X X Xunsigned int bitVector::mask(unsigned int index) const X{ X // compute the amount to shift by examining X // the low order 3 bits of the index X const unsigned int shiftAmount = index & 07; X X // make a mask by shifting the value ``1'' X // left by the given amount X return 1 << shiftAmount; X} X X X Xvoid bitVector::unionWith(bitVector& right) X{ X // form the union of set with argument set X // only works if we're both same size X assert(length() == right.length()); X X const int asize = bitValues.length(); X X for (int i = 0; i < asize; i++) X bitValues[i] |= right.bitValues[i]; X} X X X Xvoid bitVector::intersectWith(bitVector& right) X{ X // form the intersection of set with argument set X // only works if we're both same size X assert(length() == right.length()); X X const int asize = bitValues.length(); X X for (int i = 0; i < asize; i++) X bitValues[i] &= right.bitValues[i]; X} X X X Xvoid bitVector::differenceWith(bitVector& right) X{ X // form the difference of set from argument set X // only works if we're both same size X assert(length() == right.length()); X X const int asize = bitValues.length(); X X for (int i = 0; i < asize; i++) X bitValues[i] &= ~ right.bitValues[i]; X} X X X Xint bitVector::operator == (bitVector& right) X{ X // test to see if two sets are the same X // only works if we're both same size X assert(length() == right.length()); X X // test to see if every position is equal to the argument X const int asize = bitValues.length(); X X for (int i = 0; i < asize; i++) X if (bitValues[i] != right.bitValues[i]) X return 0; X X // all equal, two sets the same X return 1; X} X X X Xint bitVector::subset(bitVector& right) X{ X // return true if set is subset of argument X // only works if we're both same size X assert(length() == right.length()); X X // test to see if every position of the argument X // is a subset of the corresponding receiver position X const int asize = bitValues.length(); X X for (int i = 0; i < asize; i++) X if (right.bitValues[i] != (bitValues[i] & right.bitValues[i])) X return 0; X X return 1; X} X X X X//---------------------------------------------------------------------- X// class charSet implementation X//---------------------------------------------------------------------- X XcharSet::charSet(char * initstr) : bitVector(1024) X{ X // initialize the set with character from string X while (*initstr) X add(*initstr++); X} X X X Xvoid charSet::add(char ele) X{ X // simply invoke method from bit vector class X set((unsigned int) ele); X} X X X Xvoid charSet::deleteAllValues() X{ X for (int i = bitValues.length() - 1; i >= 0; i--) X bitValues[i] = 0; X} X X X Xint charSet::includes(char ele) const X{ X // return true if set includes argument character X return test((unsigned int) ele); X} X X X Xvoid charSet::remove(char ele) X{ X // remove argument character from set X clear((unsigned int) ele); X} END-of-bitvec.C echo x - random.C sed 's/^X//' >random.C << 'END-of-random.C' X//====================================================================== X// File: random.C X// Author: Timothy A. Budd X// Description: This file contains the implementation of the random X// number generator class. X// X// Copyright (c) 1992 by Timothy A. Budd. All Rights Reserved. X// may be reproduced for any non-commercial purpose X//====================================================================== X X#include X X Xrandom::random() X{ X // start seed with an odd prime value X seed = 44449; X} X X X Xrandom::random(unsigned int s) X{ X // allow programmer to set seed X seed = s; X} X X X Xunsigned int random::randomInteger() X{ X // return a new random positive value X const unsigned int multiplier = 15625; X const unsigned int adder = 22221; X X // modify seed, assume overflow quietly truncated X seed = multiplier * seed + adder; X X // return new seed (16 bits) X return seed & 0xFFFF; X} X X X Xdouble random::randomReal() X{ X // return a random floating point value between 0 and 1 X double dseed = randomInteger(); X X // divide by 2^16 - 1 X return dseed / 65535.0; X} X X X Xdouble random::between(double low, double high) X{ X // return a random real between low and high X return low + (high - low) * randomReal(); X} X X X Xint random::between(int low, int high) X{ X // return a random integer between low and high X double dlow = low; X double dhigh = high + 1; X X // return random real, then truncate X double result = between(dlow, dhigh); X return int(result); X} X Xint random::weightedDiscrete(vector & weights) X{ X int max = 0; X X // sum the wieghts X for (int i = 0; i < weights.length(); i++) X max += weights[i]; X X // select a random number X int rint = between(1, max); X X // find its value X for (i = 0; i < weights.length(); i++) X if (rint <= weights[i]) X return i; X else X rint -= weights[i]; X return 0; X} X X// this is needed to cause Borland C++ to generate the vector template Xstatic vector dummy(1); END-of-random.C echo x - rational.C sed 's/^X//' >rational.C << 'END-of-rational.C' X//================================================================== X// File: rational.cc X// Author: Timothy A. Budd X// Description: implementation of the rational number X// data abstraction X// Copyright (c) 1992 by Timothy A. Budd, All Rights Reserved X// Permission Granted for Duplication if not for profit X//================================================================== X# ifndef RATIONAL_C X# define RATIONAL_C X X# include X# include // rational definition X# include // assertions X# include // stream input and output X X// X// constructors X// X Xrational::rational(int numerator, int denominator) X : top(numerator), bottom(denominator) X{ X // normalize the numerator and denominator values X normalize(); X} X X// X// normalization X// X Xvoid rational::normalize() X{ // normalize rational by: X // a) move sign to numerator X // b) make sure numerator and denominator have no common divisors X int sign = 1; // sign is 1 if positive, -1 if negative X if (top < 0) { X sign = -1; X top = - top; X } X if (bottom < 0) { X sign = - sign; X bottom = - bottom; X } X X // make sure we are not dividing by zero X assert(bottom != 0); X X // find greatest common divisor X int d = gcd(top, bottom); X X // move sign to top and divide by gcd X top = sign * (top / d); X bottom = bottom / d; X} X X// X// assignments X// X Xvoid rational::operator = (const rational & right) X{ // simply copy values from right hand side of assignment X top = right.top; X bottom = right.bottom; X} X Xvoid rational::operator += (const rational & right) X{ // modify by adding right hand side X top = top * right.bottom + bottom * right.top; X bottom *= right.bottom; X X // normalize the result, insuring lowest denominator form X normalize(); X} X Xvoid rational::operator -= (const rational & right) X{ // modify by subtracting right hand side X top = top * right.bottom - bottom * right.top; X bottom *= right.bottom; X X // normalize the result, insuring lowest denominator form X normalize(); X} X Xvoid rational::operator *= (const rational & right) X{ // modify by multiplying by right hand side X top *= right.top; X bottom *= right.bottom; X X // normalize the result, insuring lowest denominator form X normalize(); X} X Xvoid rational::operator /= (const rational & right) X{ // modify by dividing by right hand side X // (same as multiplying by reciprocol) X top *= right.bottom; X bottom *= right.top; X X // normalize the result, insuring lowest denominator form X normalize(); X} X X// X// comparison X// X Xint rational::compare (const rational & right) const X{ // return negative if value is less than right X // zero if value is equal to right X // and positive if value is greater than right X return numerator() * right.denominator() - X right.numerator() * denominator(); X} X X// X// arithmetic operations X// X Xrational operator + (const rational & left, const rational & right) X{ // return addition of two rational numbers X rational result( X left.numerator() * right.denominator() + X right.numerator() * left.denominator(), X left.denominator() * right.denominator()); X return result; X} X Xrational operator - (const rational & left, const rational & right) X{ // return difference of two rational numbers X rational result( X left.numerator() * right.denominator() - X right.numerator() * left.denominator(), X left.denominator() * right.denominator()); X return result; X} X Xrational operator * (const rational & left, const rational & right) X{ // return product of two rational numbers X rational result( X left.numerator() * right.numerator(), X left.denominator() * right.denominator()); X return result; X} X Xrational operator / (const rational & left, const rational & right) X{ // return quotent of two rational numbers X rational result( X left.numerator() * right.denominator(), X left.denominator() * right.numerator()); X return result; X} X Xrational operator - (const rational & value) X{ X // return negation of a rational number X rational result( - value.numerator(), value.denominator()); X return result; X} X X// X// converions X// X Xrational::operator float() const X{ // convert rational number into single-precision floating point X return (float) top / (float) bottom; X} X X// X// misc functions X// X Xint floor(const rational & value) const X{ // return the smallest integer less than rationa number X // integer division returns the floor automatically X return value.numerator() / value.denominator(); X} X Xostream & operator << (ostream & out, const rational & value) X{ // stream output of rational number X out << value.numerator() << " / " << value.denominator(); X return out; X} X Xistream & operator >> (istream & in, rational & r) X{ // stream input of rational number X int t, b; X X // read the top X in >> t; X X // if there is a slash, read the next number X char c; X in >> c; X if (c == '/') X in >> b; // read bottom part X else { X in.putback(c); X b = 1; X } X X // do the assignment X rational newValue(t, b); X r = newValue; X X // return the stream X return in; X} X X# endif END-of-rational.C echo x - split.C sed 's/^X//' >split.C << 'END-of-split.C' X//====================================================================== X// File: split.cpp X// Author: Timothy A. Budd X// Description: This file contains the implementation of the split X// function, which splits a sentence string into words X// and returns a vector of these words. X// X// Copyright (c) 1992 by Timothy A. Budd. All Rights Reserved. X// may be reproduced for any non-commercial purpose X//====================================================================== X X#include X X// Word Structure X Xclass wordPosition X{ Xpublic: X int startingPos; X int length; X}; X Xunsigned int skipOver(string & text, unsigned int position, X const charSet & skipchars) X{ X // loop as long as we see characters from charSet X while ((text[position] != '\0') && skipchars.includes(text[position])) X position = position + 1; X X // return updated position, which may be null character X // if we ran off end of string X return position; X} X X X Xunsigned int skipTo (string & text, unsigned int position, X const charSet & haltset) X{ X // loop as long as we fail to see characters from halt set X while ((text[position] != '\0') && !haltset.includes(text[position])) X position = position + 1; X X // return updated position, which may be null character X // if we ran off end of string X return position; X} X X Xstatic int findSplitPositions(string & text, const charSet & separators, X vector & splits) X{ X // find the start and length of each word in the argument text X int lastpos = text.length(); X int numberOfWords = 0; X X // now loop over the text, looking for new words X int position = 0; X X while (position < lastpos) X { X // first skip any leading separators X position = skipOver(text, position, separators); X X // either we are at end of text X if (position < lastpos) X { X // or at beginning of a word X if (numberOfWords >= splits.length()) X splits.setSize(splits.length() + 5); X X splits[numberOfWords].startingPos = position; X X // now skip over non-separator characters X position = skipTo(text, position, separators); X X // length is current position - start X splits[numberOfWords].length = X position - splits[numberOfWords].startingPos; X numberOfWords += 1; X } X } X X // return the number of words in words array X return numberOfWords; X} X X X Xvoid split(string & text, const charSet & separators, X vector & words) X{ X // invoke procedure to compute word starting positions and lengths. X // the size of the words array is unimportant, as X // the vector will grow if necessary X vector splitPos(20); X int numberOfWords = findSplitPositions(text, separators, splitPos); X X // we now have an array of all the starting positions and lengths X // simply loop over vector to break string X words.setSize(numberOfWords, " "); X X for (int i = 0; i < numberOfWords; i++) { X words[i] = text(splitPos[i].startingPos, splitPos[i].length); X } X} END-of-split.C echo x - string.C sed 's/^X//' >string.C << 'END-of-string.C' X//====================================================================== X// File: string.cpp X// Author: Timothy A. Budd X// Description: This file contains the implementation of the X// string class. X// X// Copyright (c) 1992 by Timothy A. Budd. All Rights Reserved. X// may be reproduced for any non-commercial purpose X//====================================================================== X X# include // assertions X# include // string class X X X X//---------------------------------------------------------------------- X// calculate length of a C string X//---------------------------------------------------------------------- X Xint CstringLength(const char * str) X{ X // compute number of non-null characters in a C string X int i = 0; X X while (str[i] != '\0') X i++; X X return i; X} X X X X//---------------------------------------------------------------------- X// class string implementation X//---------------------------------------------------------------------- X Xstring::string() X{ X // create a string with no characters X // length is one, holding just null character X // allocate the new buffer X bufferlength = 1; X X // initialize buffer with null character X buffer = new char[bufferlength]; X assert(buffer != 0); X X // initialize to null X buffer[0] = '\0'; X} X X X Xstring::string(char c) X{ X // create a string with a single character X bufferlength = 2; X buffer = new char[bufferlength]; X assert(buffer != 0); X X // initialize with single character X buffer[0] = c; X buffer[1] = '\0'; X} X X X Xstring::string(int size) X{ X // create a new string with a buffer of the given size X // make sure size is positive X assert(size >= 0); X X // hold one addition char for null value X bufferlength = 1 + size; X X // allocate buffer, check allocation was successful X buffer = new char[bufferlength]; X assert(buffer != 0); X X // initialize to all null characters X for (int i = 0; i < bufferlength; i++) X buffer[i] = '\0'; X} X X X Xstring::string(const char * initialtext) X{ X // create a new string and initialize with argument value X // length is length of text, plus null char X bufferlength = 1 + CstringLength(initialtext); X X // allocate buffer X buffer = new char[bufferlength]; X assert(buffer != 0); X X // copy values into place X for (int i = 0; initialtext[i] != '\0'; i++) X buffer[i] = initialtext[i]; X X buffer[i] = '\0'; X} X X X Xstring::string(const string & initialstring) X{ X // create a new string, initializing with copy of argument X // length is length of text, plus null char X bufferlength = 1 + CstringLength(initialstring.buffer); X X // allocate buffer X buffer = new char[bufferlength]; X assert(buffer != 0); X X // copy values into place X for (int i = 0; initialstring.buffer[i] != '\0'; i++) X buffer[i] = initialstring.buffer[i]; X X buffer[i] = '\0'; X} X X X Xstring::~string() X{ X // called implicitly when a string is about to be deleted X // free the memory associated with the buffer X delete [] buffer; X X // set the pointer variable to null X buffer = 0; X} X X X Xvoid string::operator = (const string & right) X{ X // copy values of right argument into string X const int rightLength = right.length(); X X // if it doesn't fit, make a new buffer X if (rightLength >= bufferlength) X { X // delete current buffer X delete [] buffer; X X // allocate the new one X bufferlength = 1 + rightLength; X buffer = new char[bufferlength]; X assert(buffer != 0); X } X X // copy into buffer X for (int i = 0; right.buffer[i] != '\0'; i++) X buffer[i] = right.buffer[i]; X X buffer[i] = '\0'; X} X X X Xvoid string::operator += (const string & val) X{ X // append argument to end of current string X X // if there isn't space, make new buffer X int combinedLength = length() + val.length(); X X if (combinedLength > bufferlength) X { X char * newbuffer = new char [1 + combinedLength]; X assert(newbuffer != 0); X X // copy over old values X for (int i = 0; buffer[i] != '\0'; i++) X newbuffer[i] = buffer[i]; X X newbuffer[i] = '\0'; X X // delete old buffer and reset pointer X delete [] buffer; X bufferlength = 1 + combinedLength; X buffer = newbuffer; X } X X // catenate val on end of current string X int i = CstringLength(buffer); X X for (int j = 0; val.buffer[j] != '\0'; j++) X buffer[i++] = val.buffer[j]; X X buffer[i] = '\0'; X} X X X Xsubstring string::operator ()(unsigned int index, unsigned int count) X{ X // return substring consisting of count chars starting at index X X // if index out of range return empty string X if (index >= length()) X { X index = 0; X count = 0; X } X X // convert count, if necessary X int numberleft = length() - index; X X if (count > numberleft) X count = numberleft; X X // make the new string, use this to be base string X return substring(*this, index, count); X} X X X Xistream & string::getline(istream & in) X{ X // read an entire line of input into string X in.getline(buffer, bufferlength, '\n'); X return in; X} X X X Xunsigned int string::length() const X{ X // compute the number of nonull characters in a string X return CstringLength(buffer); X} X X X Xchar nothing; // global variable holding null character X Xchar & string::operator [](unsigned int index) const X{ X // return the character referenced by the index value X X // first see if the index is in bounds X if (index >= CstringLength(buffer)) X { X // not in bounds, return null character X nothing = '\0'; X return nothing; X } X X // otherwise it is a valid index, return character X return buffer[index]; X} X X X Xint string::compare(const string & val) const X{ X // compare the buffer to the argument string value X char * p = buffer; X char * q = val.buffer; X X // loop as long as both have characters and are equal X while ((*p != '\0') && (*p == *q)) X { X // inv: up to *p buffer and val are equal X p++; q++; X } X X // by subtracting the values referred to by the pointers, X // we yield a negative value if the first string is smaller X // than the second, a zero value if they are equal, X // and a positive value if the first is larger than the second X return *p - *q; X} X X X Xstring::operator const char *() const X{ X // convert string value into char pointer value, X // by returning access to the underlying C buffer X return buffer; X} X X X X//---------------------------------------------------------------------- X// relational operators X//---------------------------------------------------------------------- X Xint operator < (const string & left, const string & right) X{ return left.compare(right) < 0; } X X Xint operator <= (const string & left, const string & right) X{ return left.compare(right) <= 0; } X X Xint operator != (const string & left, const string & right) X{ return left.compare(right) != 0; } X X Xint operator == (const string & left, const string & right) X{ return left.compare(right) == 0; } X X Xint operator >= (const string & left, const string & right) X{ return left.compare(right) >= 0; } X X Xint operator > (const string & left, const string & right) X{ return left.compare(right) > 0; } X X X X//---------------------------------------------------------------------- X// function: concatenate operator X//---------------------------------------------------------------------- X Xstring operator + (const string & left, const string & right) X{ X // concatenate two strings, leaving arguments unchanged X string result(left); X result += right; X return result; X} X X X X//---------------------------------------------------------------------- X// functions: character classification X//---------------------------------------------------------------------- X Xint isUpperCase(char c) X{ X // return true if c is an upper case letter X return (c >= 'A') && (c <= 'Z'); X} X X X Xint isLowerCase(char c) X{ X // return true if c is a lower case letter X return (c >= 'a') && (c <= 'z'); X} X X X X//---------------------------------------------------------------------- X// functions: string conversions X//---------------------------------------------------------------------- X Xvoid toUpper(string & word) X{ X // convert all lower case letters to upper case X for (int i = 0; word[i] != '\0'; i++) X if (isLowerCase(word[i])) X word[i] = (word[i] - 'a') + 'A'; X} X X X Xvoid toLower(string & word) X{ X // convert all upper case letters to lower case X for (int i = 0; word[i] != '\0'; i++) X if (isUpperCase(word[i])) X word[i] = (word[i] - 'A') + 'a'; X} X X X X//---------------------------------------------------------------------- X// function: stream input for string X//---------------------------------------------------------------------- X Xistream & operator >> (istream & in, string & str) X{ X // perform string input, X // read next white-space separated word into string X // implemented using existing character input facility X char inbuffer[1000]; X X if (in >> inbuffer) X str = inbuffer; X else X str = ""; X X return in; X} X X X X//---------------------------------------------------------------------- X// class substring implementation X//---------------------------------------------------------------------- X Xsubstring::substring(string & b, int i, int c) X : base(b), index(i), count(c) X{ X // create and initialize a substring value X // no further initialization required X} X X X Xsubstring::substring(const substring & source) X : base(source.base), index(source.index), count(source.count) X{ X // create and initialize a substring value X // no further initialization required X} X X X Xvoid substring::operator = (const string & rep) const X{ X // copy a string value to a substring position X // if lengths are equal, then no new allocation necessary X if (count == rep.length()) X { X for (int i = 0; i <= count; i++) X base[index + i] = rep[i]; X X return; X } X X // otherwise compute the length of the new string X int baselen = base.length(); X int newlen = rep.length() + baselen - count; X char * newdata = new char[newlen + 1]; X X // then copy the values into the new area X for (int i = 0; i < index; i++) X newdata[i] = base[i]; X X // catenate on the new values X for (int j = 0; rep[j] != 0; j++) X newdata[i++] = rep[j]; X X // then catenate on the base X for (j = index + count; base[j] != 0; j++) X newdata[i++] = base[j]; X X newdata[i] = '\0'; X X // then change the base string X delete [] base.buffer; X base.bufferlength = newlen; X base.buffer = newdata; X X return; X} X X X Xsubstring::operator string () const X{ X // convert a substring into a string X // first copy the text into a temporary buffer X char * buffer = new char[count + 1]; X assert(buffer != 0); X X for (int i = 0; i < count; i++) X buffer[i] = base[i + index]; X X buffer[count] = '\0'; X X // then make it into a string, and delete the buffer X string result(buffer); X delete [] buffer; X return result; X} END-of-string.C echo x - hash.c sed 's/^X//' >hash.c << 'END-of-hash.c' Xtemplate void bucketSort(vector & data, X unsigned int tablesize, unsigned int (*f)(const T &)) X{ X// CFRONT error ?? X unsigned int max = data.length(): X hashTree table(tablesize, f); X X // put each element into the appropriate bucket X for (unsigned int i = 0; i < max; i++) X table.add(x[i]); X X // now put elements back into vector X hashTreeIterator itr(table); X int j = 0; X X for (itr.init(); ! itr; itr++) X x[j++] = itr(); X} X X X// bucket sort (version #2) X Xtemplate void bucketSort(vector & data, X unsigned int (*f)(const T &)) X{ X const int tablesize = 31; X unsigned int max = data.length(); X orderedList buckets[tablesize]; X X // put each element into the appropriate bucket X for (unsigned int i = 0; i < max; i++) X buckets[f(data[i])].add(data[i]); X X // now put elements back into vector X int j = 0; X X for (i = 0; i < tablesize; i++) X { X // empty the elements from the bucket X listIterator itr(buckets[i]); X X for (itr.init(); ! itr; itr++) X data[j++] = itr(); X } X} X END-of-hash.c echo x - list.c sed 's/^X//' >list.c << 'END-of-list.c' X# include X X// Copyright (c) 1992 by Timothy A. Budd. All Rights Reserved. X// may be reproduced for any non-commercial purpose X Xtemplate void listInsertionSort(vector & v) X{ X // declare an ordered list of the correct type X orderedList sorter; X X // copy the entire vector into the ordered list X // the following generates a string g++ error X vectorIterator vitr(v); X for (vitr.init(); ! vitr; ++vitr) { X sorter.add(vitr()); X } X X // now copy the values back into the array X int i = 0; X listIterator itr(sorter); X for (itr.init(); ! itr; ++itr) X v[i++] = itr(); X} END-of-list.c echo x - openHashTable.c sed 's/^X//' >openHashTable.c << 'END-of-openHashTable.c' X//================================================================== X// File: openHashTable.c X// Author: Timothy A. Budd X// Platform: Cfront X// Description: Template implementation of open addressing hash table ADT X// Copyright (c) 1992 by Timothy A. Budd, All Rights Reserved X// Permission granted for duplication if not for profit X//================================================================== X X// X// implementation file for open hash tables X// X Xtemplate XopenHashTable::openHashTable(const string & name, unsigned int (*f)(const T &)) X : hashfun(f), rfile(name) X{ X // determine size of file X size = rfile.length(); X} X Xtemplate void openHashTable::create(unsigned int sz) X{ // create a new open Hash Table with sz records X size = sz; X X // assume default constructor sets known value X T initialValue; X for (unsigned int i = 0; i < sz; i++) X rfile.put(i, initialValue); X} X Xtemplate int openHashTable::add(const T & value) X{ // add record to an open hash table X X // find initial hash value X unsigned int hashValue = (*hashfun)(value) % size; X unsigned int index = hashValue; X X // see if occupied X T currentValue; X rfile.get(index, currentValue); X while (! isEmpty(currentValue)) { X // see if next record is empty X index = index + 1; X if (index >= size) X index = 0; X if (index == hashValue) X return 0; X rfile.get(index, currentValue); X } X // found an empty position X rfile.put(index, value); X return 1; X} X X Xtemplate int openHashTable::includes(T & value) X{ X unsigned int hashValue = (*hashfun)(value) % size; X unsigned int index = hashValue; X T currentValue; X rfile.get(index, currentValue); X // loop as long as we don't see value X while (! (currentValue == value)) { X if (isEmpty(currentValue)) X return 0; X index = index + 1; X if (index >= size) X index = 0; X if (index == hashValue) X return 0; X rfile.get(index, currentValue); X } X X X // found it, set value X value = currentValue; X return 1; X} X Xtemplate void openHashTable::remove(const T & value) X{ // add record to an open hash table X X // find initial hash value X unsigned int hashValue = (*hashfun)(value) % size; X unsigned int index = hashValue; X X // see if occupied X T currentValue; X rfile.get(index, currentValue); X // loop as long as we don't see value X while (! (currentValue == value)) { X // see if next record is empty X index = index + 1; X if (index >= size) X index = 0; X if (index == hashValue) X return; X rfile.get(index, currentValue); X } X // found it, empty it out X T empty; X rfile.put(index, empty); X return; X} X X END-of-openHashTable.c echo x - priorque.c sed 's/^X//' >priorque.c << 'END-of-priorque.c' X# include X X// Copyright (c) 1992 by Timothy A. Budd. All Rights Reserved. X// may be reproduced for any non-commercial purpose X Xtemplate void buildHeap( X vector & data, int heapsize, int position) X{ X // rebuild the heap X T value = data[position]; X X while (position < heapsize) X { X // replace position with the smaller of the X // two children, or the last element X unsigned int childpos = position * 2 + 1; X X if (childpos < heapsize) X { X if ((childpos + 1 < heapsize) && X data[childpos + 1] < data[childpos]) X childpos += 1; X X // inv: childpos is smaller of two children X if (value < data[childpos]) X { X // found right location X data[position] = value; X return; X } X else X { X data[position] = data[childpos]; X position = childpos; X // recur and keep moving down X } X } X else X { X // no children X data[position] = value; X return; X } X } X} X X//---------------------------------------------------------------------- X// function: heapSort X//---------------------------------------------------------------------- X Xtemplate void heapSort(vector & data) X{ X // sort the vector argument using a heap algorithm X int max = data.length(); X X // first build the initial heap X for (int i = max / 2; i >= 0; i--) X buildHeap(data, max, i); X X // now swap the smallest element to the last position X for (i = max - 1; i > 0; i--) X { X swap(data, i, 0); X X // and rebuild the heap again X buildHeap(data, i, 0); X } X} END-of-priorque.c echo x - rstream.c sed 's/^X//' >rstream.c << 'END-of-rstream.c' X//================================================================== X// File: rstream.c X// Author: Timothy A. Budd X// Platform: Cfront X// Description: Template implementation of random access stream ADT X// Copyright (c) 1992 by Timothy A. Budd, All Rights Reserved X// Permission granted for duplication if not for profit X//================================================================== X X// X// implementation of rstream -- randomly accessed streams X// X X# include "string.h" X# include X# include X Xtemplate rstream::rstream(const string & name) X{ X // convert string to C style pointer variable X const char * cname = name; X // open the file for both input and output X theStream.open(cname, ios::in | ios::out); X} X Xtemplate int rstream::get(unsigned int index, T & value) X{ X // first position the stream X theStream.seekg(sizeof( T ) * index); X // then read the value X char * valuePtr = (char *) & value; X theStream.read(valuePtr, sizeof( T )); X // return the number of characters read X return theStream.gcount(); X} X Xtemplate void rstream::put(unsigned int index, const T & value) X{ X // first position the stream X theStream.seekg(sizeof( T ) * index); X // then write the value X const char * valuePtr = (const char *) & value; X theStream.write(valuePtr, sizeof( T )); X} X Xtemplate unsigned int rstream::length() X{ X if (! theStream) X return 0; X else { X theStream.seekg(0, ios::end); X return theStream.tellg() / sizeof( T ); X } X} X X// X// stream iterators X// X Xtemplate rstreamIterator::rstreamIterator (rstream & bs) X : baseStream(bs) X{ X index = 0; X} X Xtemplate rstreamIterator:: X rstreamIterator (const rstreamIterator & x) X : baseStream(x,baseStream), index(x.index) X{ X // no further initialization X} X Xtemplate T rstreamIterator::operator() () X{ X T result; X baseStream.get(index, result); X return result; X} X X Xtemplate int rstreamIterator::init() X{ X index = 0; X return operator ! (); X} X Xtemplate int rstreamIterator::operator ! () X{ X T temp; X // if we can read a value, we aren't at the end X if (baseStream.get(index, temp) != 0) X return 1; X // this resets the stream pointer X baseStream.get(0, temp); X return 0; X} X Xtemplate int rstreamIterator::operator ++ () X{ X index++; X return operator ! (); X} X Xtemplate void rstreamIterator::operator = (T value) X{ // simply assign the value the current position X baseStream.put(index, value); X} X END-of-rstream.c echo x - tree.c sed 's/^X//' >tree.c << 'END-of-tree.c' X// Copyright (c) 1992 by Timothy A. Budd. All Rights Reserved. X// may be reproduced for any non-commercial purpose X X# include X Xtemplate void treeSort(vector & v) X{ X // declare an search tree of the correct type X avlTree sorter; X X // copy the entire vector into the tree X vectorIterator vitr(v); X X for (vitr.init(); ! vitr; ++vitr) X sorter.add(vitr()); X X // now copy the values back into the array X int i = 0; X searchTreeIterator itr(sorter); X X for (itr.init(); ! itr; ++itr) X v[i++] = itr(); X} END-of-tree.c echo x - vector.c sed 's/^X//' >vector.c << 'END-of-vector.c' X// Copyright (c) 1992 by Timothy A. Budd. All Rights Reserved. X// may be reproduced for any non-commercial purpose X X//---------------------------------------------------------------------- X// function: binarySearch X//---------------------------------------------------------------------- X Xtemplate Xint binarySearch(VecType data, EleType ele, unsigned int max) X{ // perform binary search on a vector X X unsigned int low = 0; X unsigned int high = max; X X while (low < high) { X X // inv: data[0..low-1] are all lexx than ele X // data[high..max] are all greater than ele X unsigned int mid = (low + high) / 2; X if (data[mid] < ele) X low = mid + 1; X else X high = mid; X } X X // return element for which data[0..low-1] < ele <= data[low] X return low; X} X X//---------------------------------------------------------------------- X// function: swap X//---------------------------------------------------------------------- X Xtemplate void swap( vector & data, int i, int j) X{ X // swap the values at positions i and j X T temp = data[i]; X data[i] = data[j]; X data[j] = temp; X} X X X//---------------------------------------------------------------------- X// function: bubbleSort X//---------------------------------------------------------------------- X Xtemplate void bubbleSort(vector & data) X{ X // sort, in place. the argument vector into ascending order X for (int top = data.length() - 1; top > 0; top--) X { X // find the largest element in position 0..top X // place in data[top] X for (int i = 0; i < top; i++) X { X // inv: data[i] is largest element in 0..i X if (data[i+1] < data[i]) X swap(data, i+1, i); X X // inv: data[i+1] is largest element in 0..i+1 X } X X // inv: data[top..length-1] is properly ordered X } X} X X X X//---------------------------------------------------------------------- X// function: selectionSort X//---------------------------------------------------------------------- X Xtemplate void selectionSort(vector & data) X{ X // sort, in place. the argument vector into ascending order X for (int top = data.length() - 1; top > 0; top--) X { X // find the position of the largest element X int largeposition = 0; X X for (int j = 1; j <= top; j++) X { X // inv: data[largeposition] is largest element X // in 0..j-1 X if (data[largeposition] < data[j]) X largeposition = j; X X // inv: data[largeposition] is largest element in 0..j X } X X if (top != largeposition) X swap(data, top, largeposition); X X // inv: data[top..n] is ordered X } X} X X X//---------------------------------------------------------------------- X// function: insertionSort X//---------------------------------------------------------------------- X Xtemplate void insertionSort(vector & data) X{ X // sort, in place. the argument vector into ascending order X int n = data.length(); X X for (int top = 1; top < n; top++) X { X // inv: data[0..top-1] is ordered X // goal: place element data[top] in the proper position X for (int j = top - 1; j >= 0 && data[j+1] < data[j]; j--) { X swap(data, j, j+1); X } X X // inv: data[0..top] is ordered X } X X // inv: data[0..n-1] is ordered X} X X//---------------------------------------------------------------------- X// partition and quicksort X//---------------------------------------------------------------------- X Xtemplate Xint partition(vector & v, int low, int high, int pivotIndex) X{ X // move the pivot value to the bottom of the vector X if (pivotIndex != low) X swap(v, low, pivotIndex); X pivotIndex = low; X low++; X X // invarient: X // v[i] for i less than low are less than or equal to pivot X // v[i] for i greater than high are greater than pivot X X // move elements into place X while (low <= high) { X if (v[low] <= v[pivotIndex]) X low++; X else if (v[high] > v[pivotIndex]) X high--; X else X swap(v, low, high); X } X X // put pivot back between two groups X if (high != pivotIndex) X swap(v, pivotIndex, high); X return high; X} X Xtemplate XT findElement(vector & v, int N, int low, int high) X{ X // first select a pivot X int pivotIndex = (high + low)/2; X X // partition the vector X pivotIndex = partition(v, low, high, pivotIndex); X X // see if we are done X if (pivotIndex == N) X return v[N]; X X // else try again X if (N < pivotIndex) X return findElement(v, N, low, pivotIndex); X else X return findElement(v, N, pivotIndex, high); X} X Xtemplate Xvoid quackSort(vector & v, int low, int high) X{ X // no need to sort a vector of zero or one elements X if (low >= high) X return; X X // select the pivot value X int pivotIndex = (low + high) / 2; X X // partition the vector X pivotIndex = partition(v, low, high, pivotIndex); X X // sort the two sub arrays X if (low < pivotIndex) X quackSort(v, low, pivotIndex - 1); X if (pivotIndex < high) X quackSort(v, pivotIndex + 1, high); X} X Xtemplate Xvoid quackSort(vector & v) X{ X quackSort(v, 0, (int) v.length() - 1); X} X END-of-vector.c echo x - vertex.c sed 's/^X//' >vertex.c << 'END-of-vertex.c' X//================================================================== X// File: vertex.c X// Author: Timothy A. Budd X// Platform: Cfront X// Description: Template implementation of graph vertex X// Copyright (c) 1992 by Timothy A. Budd, All Rights Reserved X// Permission granted for duplication if not for profit X//================================================================== X X# include X Xtemplate vertex::vertex() X{ X // do nothing X} X Xtemplate vertex::vertex(T init) : value(init) X{ X // do nothing X} X Xtemplate void vertex::addArc(vertex & x) X{ X arcs.add(x); X} X Xtemplate Xint operator == (const vertex left, const vertex & right) X{ X return left.value == right.value; X} X END-of-vertex.c exit