#if ! defined _Bag_h #define _Bag_h 1 #include #include #include #include #include namespace omega { template class Bag : public Collection { public: virtual ~Bag(); Bag(); Bag(const Bag&); Bag & operator=(const Bag&); //! add elements in b virtual void operator |= (const Bag & b); Iterator *new_iterator(); bool empty() const; void remove(T); virtual void insert(T); void clear(); virtual bool contains(T) const; int size() const; T extract(); // protected: breaks g++ 261 List_Element* contents; }; template class Ordered_Bag : public Bag { public: Ordered_Bag(); Ordered_Bag(const Ordered_Bag& B) : Bag(B) {} void insert(T); //! add elements in b virtual void operator |= (const Ordered_Bag & b); //! add elements in b void operator |= (const Bag & b); bool contains(T) const; bool operator == (const Ordered_Bag&) const; bool operator != (const Ordered_Bag&) const; bool operator < (const Ordered_Bag&) const; }; template class Set : public Ordered_Bag { public: Set(); Set(T); Set(const Set& S) : Ordered_Bag(S) {} bool contains (const Set& b) const; bool contains (T t) const { return Ordered_Bag::contains(t); } // the above makes "standard" C++ happy //! add elements in b virtual void operator |= (const Set & b); //! add elements in b void operator |= (const Ordered_Bag & b); //! add elements in b void operator |= (const Bag & b); //! delete items also in b void operator -= (const Set & b); //! delete items not in b void operator &= (const Set & b); //! check for elements in common bool operator & (const Set &) const; }; } // namespace #define instantiate_Bag(T) template class Bag; \ instantiate_List_Element(T); #define instantiate_Ordered_Bag(T) template class Ordered_Bag; \ instantiate_Bag(T) #define instantiate_Set(T) template class Set; \ instantiate_Ordered_Bag(T) namespace omega { template Bag::Bag() { contents = new List_Element ; contents->tail = 0; } template Bag::~Bag() { delete contents; } template Ordered_Bag::Ordered_Bag() {} template Set::Set() {} template Bag::Bag(const Bag &L) { contents = new List_Element(*L.contents); } template Bag & Bag::operator=(const Bag &L) { if (this != &L) { delete contents; contents = new List_Element(*L.contents); } return *this; } template Set::Set(T e) { assert(this->contents); this->contents->tail = new List_Element(e, 0); } /**************************************************************** * * * Misc. simple Collection operations * * * ****************************************************************/ template bool Bag::empty() const { return contents->tail == 0; } template Iterator *Bag::new_iterator() { return new List_Element_Iterator(contents->tail); } template void Bag::clear() { if (contents->tail) delete contents->tail; contents->tail = 0; } template int Bag::size() const { int i = 0; List_Element * p = contents->tail; while (p) { p = p->tail; i++; }; return i; } /**************************************************************** * * * Collection/Element operations (e.g. insert, contains) * * * ****************************************************************/ template void Bag::remove(T e) { List_Element * p = contents; while (p->tail && p->tail->head != e) p = p->tail; if (p->tail && p->tail->head == e) { List_Element * q = p->tail; p->tail = q->tail; q->tail = 0; delete q; } } template T Bag::extract() { List_Element * p = contents->tail; T e = p->head; contents->tail = p->tail; p->tail = 0; delete p; return e; } template void Bag::insert(T e) { List_Element * q = new List_Element(e,contents->tail); contents->tail = q; } template void Ordered_Bag::insert(T e) { List_Element * p = this->contents; while (p->tail && p->tail->head < e) p = p->tail; if (!p->tail || p->tail->head != e) { List_Element * q = new List_Element(e,p->tail); p->tail = q; } } template bool Bag::contains(T e) const { List_Element * p = contents; while (p->tail && p->tail->head != e) p = p->tail; return (p->tail && p->tail->head == e); } template bool Ordered_Bag::contains(T e) const { List_Element * p = this->contents; while (p->tail && p->tail->head < e) p = p->tail; return (p->tail && p->tail->head == e); } template bool Set::contains (const Set& b) const { List_Element * p = this->contents; List_Element * q = b.contents; do { /* consume matched elements in p and q */ p = p->tail; q = q->tail; if (!q) return 1; /* no more elements to match */ if (!p) return 0; /* nothing left in p to match with */ if (q->head < p->head) { /* nothing smaller than p->head left in p, so q->head can't be matched */ return 0; }; while (p && p->head < q->head) { /* toss away some elements from p */ p = p->tail; } if (!p || q->head < p->head) return 0; } while (q); return 1; } /**************************************************************** * * * Collection/Collection operations (e.g. |=) * * * ****************************************************************/ template void Bag::operator |= (const Bag & b) { assert(this != &b); List_Element * q = b.contents->tail; while (q) { List_Element * r = new List_Element(q->head,contents->tail); contents->tail = r; q = q->tail; } } template void Ordered_Bag::operator |= (const Ordered_Bag & b) { if (this == &b) return; List_Element * p = this->contents; List_Element * q = b.contents->tail; while (q) { while (p->tail && p->tail->head < q->head) p = p->tail; List_Element * r = new List_Element(q->head,p->tail); p->tail = r; q = q->tail; } } template void Ordered_Bag::operator |= (const Bag & b) { Ordered_Bag tmp; for (List_Element *p = b.contents; p; p=p->tail) { tmp.insert(p->head); } *this |= tmp; } template void Set::operator |= (const Set & b) { if (this == &b) return; List_Element * p = this->contents; List_Element * q = b.contents->tail; while (q) { while (p->tail && p->tail->head < q->head) p = p->tail; if (!p->tail || p->tail->head != q->head) { List_Element * r = new List_Element(q->head,p->tail); p->tail = r; } q = q->tail; } } template void Set::operator |= (const Ordered_Bag & b) { Set tmp; for (List_Element *p = b.contents; p; p=p->tail) { tmp.insert(p->head); } *this |= tmp; } template void Set::operator |= (const Bag & b) { Set tmp; for (List_Element *p = b.contents; p; p=p->tail) { tmp.insert(p->head); } *this |= tmp; } // delete items also in b template void Set::operator -= (const Set & b) { if (this == &b) { this->clear(); return; } List_Element * p = this->contents; List_Element * q = b.contents->tail; while (q) { while (p->tail && p->tail->head < q->head) p = p->tail; if (p->tail && p->tail->head == q->head) { List_Element * r = p->tail; p->tail = r->tail; r->tail = 0; delete r; } q = q->tail; } } // delete items not in b template void Set::operator &= (const Set & b) { if (this == &b) return; List_Element * p = this->contents; List_Element * q = b.contents->tail; while (q) { while (p->tail && p->tail->head < q->head) { List_Element * r = p->tail; p->tail = r->tail; r->tail = 0; delete r; }; if (p->tail && p->tail->head == q->head) { /* allow p->tail->head into the result */ p = p->tail; } /* q->head has matched anything it is going to match */ q = q->tail; } if (p->tail) { delete p->tail; p->tail = 0; }; } template bool Set::operator & (const Set& b) const { List_Element * p = this->contents; List_Element * q = b.contents; do { p = p->tail; q = q->tail; while (p && q && p->head != q->head) { while (p && p->head < q->head) p = p->tail; while (p && q && q->head < p->head) q = q->tail; }; if (p && q && p->head == q->head) return 1; } while (p && q); return 0; } template bool Ordered_Bag::operator == (const Ordered_Bag& b) const { List_Element * p = this->contents; List_Element * q = b.contents; while (1) { p = p->tail; q = q->tail; if (!p && !q) return 1; if (!p || !q) return 0; if (p->head != q->head) return 0; }; } template bool Ordered_Bag::operator != (const Ordered_Bag& b) const { return !(*this == b); } template bool Ordered_Bag::operator < (const Ordered_Bag& b) const { List_Element * p = this->contents; List_Element * q = b.contents; while (1) { p = p->tail; q = q->tail; if (!p && !q) return 0; if (!p) return 1; if (!q) return 0; if (p->head < q->head) return 1; if (q->head < p->head) return 0; }; return 1; } } // namespace #endif