//AssocList.h
// An AssocList f holds a set of(key, value) associations,
// (just like a HashTable, except operations are slower)
//
// basic operations are:
//
// f[key] = value -- assign a value associated with key
// value = f[key] -- retrieve the value associated with key.
// If there was no association, allocate a new association
// with the value optionally set to some default.
//
// f.exists(key) -- does key have a value associated with it?
// f.remove(key) -- remove the association for key (if one exists)
//
// f.clear() -- remove all associations
//
// f.keys() -- return array of existing keys
// f.values() -- return array of existing values
//
// also: copy constructor, operator=, operator<<
//
// use like this:
//
// #include "AssocList.h"
// #include "AssocList.cc"
//
// ...
//
// AssocList<char *, int> h(-1); // with default initialization value
// AssocList<char *, int> g; // without default initialization value
//
// h["hi"] = 3;
//
// Array<char *> keys = h.keys();
//
// for (int i = 0; i < keys.size(); ++i)
// cout << h[keys[i]] << endl;
//
// Array<int> keys = h.values();
//
// h.remove("hi");
//
// h.clear();
//
// g = h; // deep copy by operator=
//
// if (h.exists("hi")) ... // test if "hi" is a key without creating an entry for it
//
// Implementated as an array of (key, value) pairs, so...
// MOST OPERATIONS TAKE O(N) TIME, WHERE N IS THE NUMBER OF ASSOCIATIONS.
// (only useful for small lists)
#ifndef _ASSOCLIST_H
#define _ASSOCLIST_H
#include "Array.h"
#include "Comparisons.h"
#include <iostream.h>
template <class KEY, class VALUE>
class AssocList {
public:
// construct an AssocList default init value for new VALUES:
AssocList(VALUE const & def);
// construct an AssocList without any default init value
AssocList();
// deep copy constructor
AssocList(AssocList const & a);
// assignment op (deep copy)
AssocList& operator=(const AssocList& a);
// destructor
~AssocList();
// reset to empty
void clear();
// does key have an entry?
int exists(KEY const & k) const;
// remove entry of key
void remove(KEY const & k);
// return ref to value associated with key
VALUE & operator[](KEY const & k);
// return value associated with key, key must exist
VALUE operator[](KEY const & k) const;
// return array of all keys with entries
Array<KEY> keys() const;
// return array of all values associated with keys
Array<VALUE> values() const;
// output
friend ostream & operator<< <>(ostream &, const AssocList<KEY,VALUE> &);
private:
// implementation is as array of (KEY,VALUE) pairs,
// with non-replaced removed pairs marked "removed"
struct Pair { KEY k; VALUE v; int removed; };
Array<Pair> pairs;
int use_default; // 1 = use, 0 = don't use
VALUE default_init; // only used if use_default = 1
int find(KEY const & k) const; // return index of pair with key k
};
#endif