//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