460 likes | 661 Views
Sets and Maps. Andy Wang Data Structures, Algorithms, and Generic Programming. Sets. Abstract associative containers Set Stores objects Unimodal: duplicate objects not allows MultiSet Stores objects Multimodal: duplicate objects OK Also known as bags. Maps.
E N D
Sets and Maps Andy Wang Data Structures, Algorithms, and Generic Programming
Sets • Abstract associative containers • Set • Stores objects • Unimodal: duplicate objects not allows • MultiSet • Stores objects • Multimodal: duplicate objects OK • Also known as bags
Maps • Abstract associative containers • Map • Stores (key, object) pairs • Unimodal: duplicate keys not allows • AKA: table, associative array • MultiMap • Stores (key, object) pairs • Multimodal: duplicate keys OK
Client Needs • Insert an object • Remove a specified object • Remove all copies of an object • Inspect an object • Iterate through all objects • Optional • Performance constraints • Iteration order constraints
Client Does Not Need • Implementation details • Data structure used to implement the container
Example Set Clients • Inventory struct StockItem { // barcode, name, amount }; void print_inventory(std::ostream&os, const set<StockItem>& inventory) { set<StockItem>::Iterator; for (I = inventory.Begin(); I != inventory.End(); ++I) { os << *I; } }
Example Set Clients • Customer accounts class Customer { // ssn, account_number, last_name, first_name… }; int main() { set<Customer> customers; }
Example Set Clients • Exceptional instances set<String> dictionary; set<String> wordset; set<String> unknown = wordset – dictionary; for (set<String>::Iterator I = unknown.Begin(); I != unknown.End(); ++I) { std::cout << *I << endl; // output possible mispelled words }
Example Set Clients • Instances in common set<widget> S1, S2; set<widget> S = S1 * S2; // S contains the widgets that are in both S1 and S2
Example Set Clients • Password server struct User { String username; unsigned long signature; }; class PWServer { set<User> users; … };
Example Set Clients • Password server int PWServer::CheckPW(const String uid, const String pw) { String uid_pw(uid + pw); unsigned long hash = secure_hash_function(uid_pw); User u(uid, hash); set<User>::Iterator I = users.Includes(u); if ((*I).username == u.username) && (*I).signature == user.signature)) { return 1; } return 0; }
Example Set Clients • Any map client • typedef set<pair<K, V> > map<K, V>;
Example Map Clients • Password server typedef String username; typedef unsigned long signature; class PWServer { map <username, signature> users; … }; int PWServer::CheckPW(const String & uid, const String &pw) { unsigned long hash = secure_hash_function(uid + pw); map<username, signature>:: Iterator I = users.Includes(uid); if (I.Valid() && (*I).key == uid && (*I).value = signature) { return 1; } return 0; }
Example Map Clients • Internet router map <DestIPNumber, NextHopIPNumber> routemap; • Dictionary map <Word, Definition> dictionary; • Keyword index map <Word, List<page_numbers> > concordance;
Set Tools (Sorted) • Sorted sets • CSet<T, C> adaptor • Classic choices for C: sorted list, binary search tree, or red-black tree • Adaptation of sorted associative container • Search operations: LowerBound(), UpperBound(), and Includes() • Sorted order traversal • Operators: union, intersection, difference, subset • Modality determined by adaptee
Map Tools (Sorted) • Sorted maps • CMap and CMultiMap adaptors • Adaptation of sorted associative container • Search operations: LowerBound(), UpperBound(), and Includes() • Sorted order traversal • Generic set algorithms apply • Modality determined by adaptor
Set and Map Tools (Sorted) • Client usage • CSet<char, TUSList<char> > S1; • Sorted list • Unimodal • CSet<char, TMSList<char, TGreaterThan<char> > > S2; • Sorted list in reverse order • Multimodal • CMap<String, int, TUSList<TAssociation<String, int> > > S3 • Sorted list • Unimodal
Set and Map Tools (Sorted) typedef String key_type; typedef int data_type; typedef TAssociation<key_type, data_type> pair_type; typedef special_class predicate_type; typedef TMBST<pair_type, predicate_type> container_type; CMultiMap<key_type, container_type> M1; • Binary search tree • Multimodal • Special predicate class
Set and Map Tools (Unsorted) • Unsorted sets and maps • CHashSet, CHashMultiSet adaptors • CHashMap, CHashMultiMap adaptors • Adaption as vector of containers • Search operation: Includes() • Random order traversal • Modality determined by adaptor
The CSet Adaptor template <typename T, class C> class CSet { friend class CSetIterator<K, V, C>; public: typedef T value_type; typedef C container_type; typedef CSetIterator<T, C> Iterator; // constructors CSet() : c() { } CSet(const CSet<T, C>& S) : c(S.c) { } ~CSet() { Clear(); } CSet<T, C>&operator=(const CSet<T, C>& S) { if (this != &S) { c = S.c; } return *this; }
The CSet Adaptor // element operations Iterator Insert(const value_type& t) { CSet<T, C>::Iterator I; I.i = c.Insert(t); return I; } int Insert(Iterator& I, const value_type& t) { return c.Insert(I.i, t); } size_t Remove(const value_type& t) { return c.Remove(t); } int Remove(Iterator& I) { return c.Remove(I.i); } void Clear() { c.Clear(); }
The CSet Adaptor // locator operations Iterator LowerBound(const value_type& t) const { CSet<T, C>::Iterator I; I.i = c.LowerBound(t); return I; } Iterator UpperBound(const value_type& t) const { CSet<T, C>::Iterator I; I.i = c.UpperBound(t); return I; } Iterator Includes(const value_type& t) const { CSet<T, C>::Iterator I; I.i = c.Includes(t); return I; }
The CSet Adaptor Iterator Begin() const { CSet<T, C>::Iterator I; I.i = c.Begin(t); return I; } Iterator End() const { CSet<T, C>::Iterator I; I.i = c.End(t); return I; } Iterator rBegin() const { CSet<T, C>::Iterator I; I.i = c.Begin(t); return I; } Iterator rEnd() const { CSet<T, C>::Iterator I; I.i = c.rEnd(t); return I; }
The CSet Adaptor // size operations int Empty() const { return c.Empty(); } size_t Size() const { return c.Size(); } protected: C c; };
Global Operators on CSet // containment operators bool operator<=(const CSet<T, C>& S1, const CSet<T, C>& S2) { return g_subset_of(S1.Begin(), S1.End(), S2.Begin(), S2.End(); } bool operator<(const CSet<T, C>& S1, const CSet<T, C>& S2) { return (S1.Size() < S1.Size() && S1 <= S2); } bool operator>=(const CSet<T, C>& S1, const CSet<T, C>& S2) { return S2 <= S1; } bool operator>(const CSet<T, C>& S1, const CSet<T, C>& S2) { return S2 < S1; }
Global Operators on CSet // union CSet<T, C> operator+(const CSet<T, C>& S1, const CSet<T, C>& S2) { CSet<T, C> S; InsertIterator<CSet<T, C> > I(S); g_set_union(S1.Begin(), S1.End(), S2.Begin(), S2.End(), I); return S; } // difference CSet<T, C> operator-(const CSet<T, C>& S1, const CSet<T, C>& S2) { CSet<T, C> S; InsertIterator<CSet<T, C> > I(S); g_set_difference(S1.Begin(), S1.End(), S2.Begin(), S2.End(), I); return S; }
Global Operators on CSet CSet<T, C> operator*(const CSet<T, C>& S1, const CSet<T, C>& S2) { CSet<T, C> S; InsertIterator<CSet<T, C> > I(S); g_set_intersection(S1.Begin(), S1.End(), S2.Begin(), S2.End(), I); return S; } bool operator==(const CSet<T, C>& S1, const CSet<T, C>& S2) { if (S1.Size() != S2.Size()) { return 0; } CSet<T, C>::Iterator I1(S1), I2(S2); while (I1.Valid() { if (*(I1++) != *(I2++)) { return 0; } } return 1; }
Global Operators on CSet bool operator!=(const CSet<T, C>& S1, const CSet<T, C>& S2) { return !(S1 == S2); } template<typename T, class C> std::ostream operator<<(std::ostream& os, const CSet<T, C>& S) { CSet<T, C>::Iterator I; for (I = S.Begin(); I != S.End(); ++I) { os << *I; } return os; }
The CSetIterator Adaptor template <typename T, class C> class CSetIterator { friend class CSet<T, C>; public: // constructors CSetIterator() : i() { } CSetIterator(const CSet<T, C>& S) : i() { i = S.c.Begin(); } CSetIterator(const CSetIterator<T, C>& I) : i(I.i) { } // initializers void Initialize(const CSet<T, C>& S) { i.Initialize(S.c); } void rInitialize(cocnst CSet<T, C>& S) { i.rInitialize(S.c); } // informationals value_type& Retrieve() const { return i.Retrieve(); } int Valid() const { return i.Valid(); }
The CSetIterator Adaptor // operators int operator==(const CSetIterator<T, C>& I2) const { return i == I2.i; } int operator!=(const CSetIterator<T, C>& I2) const { return i != I2.i; } value_type& operator*() const { return *i; } CSetIterator<T, C>& operator=(const CSetIterator<T, C> &I) { i = I.i; return *this; } CSetIterator<T, C>& operator++() { ++i; return *this; } CSetIterator<T, C>& operator++(int) { CSetIterator<T, C> I = *this; CSetIterator<T, C>::operator++(); return I; }
The CSetIterator Adaptor CSetIterator<T, C>& operator--() { --i; return *this; } CSetIterator<T, C>& operator--(int) { CSetIterator<T, C> I = *this; CSetIterator<T, C>::operator--(); return I; } protected: typename C::Iterator i; };
The CMap Adaptor template <typename K, class V, class C> class CMap { friend class CMapIterator<K, V, C>; public: typedef K key_type; typedef C container_type; typedef typename C::value_type value_type; typedef CMapIterator<K, V, C> Iterator; // proper type CMap() : c() { } CMap(const CMap<K, V, C>& M) : c(M.c) { } ~CMap() { c.Clear(); } CMap& operator=(const CMap<K, V, C>& M) { if (this != M) { c = M.c; } return *this; }
The CMap Adaptor // associative array operator: unimodal V& operator[](const K& k) { TAssociation<K, V> p; p.key = k; typename C::Iterator i = c.LowerBound(p); if (!i.Valid() || p != *i) { // if not in map or not identical key c.Insert(i, p); } return (*i).value; }
The CMap Adaptor Iterator Insert(const K& k, const V& v) { TAssociation<K, V> p; Iterator I; I.i = c.LowerBound(p); if (!I.Valid() || p != *I) { // not found if (c.Insert(I.i, p) { return I; } else { return End(); } } (*I).value = v; // overwrite if found return I; } int Insert(Iterator& I, const K& k, const V& v) { TAssociation<K, V> p(k, v); return c.Insert(I.i, p); }
The CMap Adaptor unsigned int Remove(const K& k) { TAssociation<K, V> p; p.key = k; return c.Remove(p); } int Remove(Iterator& I) { return c.Remove(I.i); } void Clear() { return c.Clear(); } // size operations unsigned long Size() const { return c.Size(); } int Empty() const { return c.Empty(); }
The CMap Adaptor // locator operations Iterator Includes(const K& k) const { CMapIterator<K, V, C> I; TAssociation<K, V> p; p.key = k; I.i = c.LowerBound(p); if (I.Valid() && (k == (*I).key) { return I; } return End(); } Iterator LowerBound(const K& k) const { … } Iterator UpperBound(const K& k) const { … }
The CMap Adaptor Iterator Begin() const { CMapIterator<K, V, C> I; I.i = c.Begin(); return I; } Iterator End() const {…} Iterator rBegin() const {…} Iterator rEnd() const {…} protected: C c; };
The CMapIterator template<typename K, class V, class C> class CMapIterator { friend class CMap<K, V, C> public: // bidirectional iterator interface protected: typename C::Iterator i; }
The CMultiMap Adaptor template<typename K, class V, class C> class CMultiMap { friend class CMapIterator<K, V, C> public: typedef K key_type; typedef C container_type; typedef typename C::value_type value_type; typedef CMapIterator<K, V, C> Iterator; // proper type CMultiMap() : c() { } CMultiMap(const CMultiMap<K, V, C>& MM) : c(MM.c) { } ~CMultiMap() { c.Clear(); } CMultiMap& operator=(const CMultiMap& MM) { … }
The CMultiMap Adaptor // operators Iterator Insert(const K& k, const V& v) { Tassociation<K, V> p(k, v); Iterator I; I.i = c.Insert(p); return I; } int Insert(Iterator& I, const K& k, const V& v) { TAssociation<K, V> p(k, v); return c.Insert(I.i, p); } unsigned int Remove(const K& k) { TAssociation<K, V> p; p.key = k; return c.Remove(p); } int Remove(Iterator& I) { return c.Remove(I.i); } void Clear() { return c.Clear(); }
The CMultiMap Adaptor // size operations unsigned long Size() const { return c.Size(); } int Empty() const { return c.Empty(); } // locator operations Iterator Includes(const K& k) const { Iterator I; TAssociation<K, V> p; p.key = k; I.i = c.Includes(p); return I; } Iterator LowerBound(const K& k) const { … } Iterator UpperBound(const K& k) const { … }
The CMultiMap Adaptor Iterator Begin() const { CMultiMapIterator<K, V, C> I; I.i = c.Begin(); return I; } Iterator End() const {…} Iterator rBegin() const {…} Iterator rEnd() {…} protected: C c; }
The CHashSet Adaptor template <typename T, class H, class C> class CHashSet { friend class CHashSetIterator<T, H, C>; public: typedef T value_type; typedef H hash_type; typedef C bucket_type; typedef CHashSetIterator<T, H, C> Iterator; // constructor CHashSet(size_t number_of_buckets); ~CHashSet(); // element operations Iterator Insert(const value_type& t); int Insert(Iterator& I, const value_type& t); size_t Remove(const value_type& t); int Remove(Iterator& I); void Clear();
The CHashSet Adaptor // locator operations Iterator Includes(const value_type& t) const; Iterator Begin() const; Iterator End() const; Iterator rBegin() const; Iterator rEnd() const; // size operations int Empty() const; size_t Size() const; protected: size_t numBuckets; TVector<C> bucketVector; H hashObject; private: CHashSet(const CHash<T, H, C>&); CHashSet& operator=(const CHashSet&); };
The CHashSetIterator Adaptor template <typename T, class H, class C> class CHashSetIterator { friend class CHashSet<T, H, C>; public: // bidirectional iterator public interface protected: const CHashSet<T, H, C> *setPtr; typename C::Iterator bucketItr; size_t bucketNum; };