/* * * Copyright (C) 1997-2012, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by * * OFFIS e.V. * R&D Division Health * Escherweg 2 * D-26121 Oldenburg, Germany * * * Module: ofstd * * Author: Thomas Wilkens * * Purpose: Template class for administrating an unordered set of elements * of an arbitrary type. * */ #ifndef OFUnorderedSet_h #define OFUnorderedSet_h #include "dcmtk/config/osconfig.h" #include "dcmtk/ofstd/oftypes.h" #include "dcmtk/ofstd/ofset.h" /** This template class provides a data structure and operations for administrating an * unordered set of elements of an arbitrary type. Note the following properties of this * class: * - an element which is inserted into the set will be copied * - the datatype of the set's elements has to support operator== so that it is possible * to find a certain element * - it is allowed to insert identical elements into the set * - if a user requires to remove a certain element and if there are several elements * which are identical to this element, only one element will be removed from the set * - after removing an element of a set, the indeces of the set's elements might have * changed; hence, looping over all elements of a set must be restarted if an element * was removed from the set within the loop * - the order of the elements is arbitrary, but it will not be changed unless an element * is removed from the set */ template class OFUnorderedSet : public OFSet { protected: public: /** Default constructor. */ OFUnorderedSet() : OFSet() { } /** Copy constructor. * @param src Source object of which this will be a copy. */ OFUnorderedSet( const OFUnorderedSet &src ) : OFSet( src ) { } /** Destructor. */ virtual ~OFUnorderedSet() { } /** operator=. * @param src Source object whose values will be assigned to this. * @return Reference to this. */ const OFUnorderedSet &operator=( const OFUnorderedSet &src ) { if( this == &src ) return( *this ); OFSet::operator=( src ); return( *this ); } /** Determines if two sets are identical. * @param other Set which shall be compared with this. * @return OFTrue if sets are identical, OFFalse otherwise. */ virtual OFBool operator==( const OFUnorderedSet &other ) const { // check if both sets contain the same // amount of items; if not, return OFFalse if( OFSet::num != other.num ) return( OFFalse ); // initialize result with OFTrue OFBool result = OFTrue; // make a copy of this OFUnorderedSet s = *this; // as long as result is OFTrue go through all items in other for( unsigned int i=0 ; i &other ) const { return( !( *this == other ) ); } /** Inserts a new item into the set. * @param item Item which shall be inserted into the set. */ virtual void Insert( const T &item ) { // if size equals num, we need more space if( OFSet::size == OFSet::num ) this->Resize( OFSet::size * 2 ); // copy item T *newItem = new T( item ); // insert copy into array OFSet::items[OFSet::num] = newItem; // increase counter OFSet::num++; } /** Inserts all items of another set into this set. * @param other set whose items shall be inserted into the set. */ virtual void Insert( const OFUnorderedSet &other ) { // go through all items in other and insert each item into this for( unsigned int i=0 ; i::num && !itemDeleted ; i++ ) { // if current item is the one which shall be deleted if( *OFSet::items[i] == item ) { // delete item delete OFSet::items[i]; // and - so that there are no holes in the array - move the last // item to the array field from which the item was deleted; // only do so in case we did _not_ delete the last item if( i != OFSet::num - 1 ) { OFSet::items[i] = OFSet::items[OFSet::num-1]; OFSet::items[OFSet::num-1] = NULL; } else OFSet::items[i] = NULL; // reduce counter OFSet::num--; // remember that an item was deleted (so that always only one item will be deleted) itemDeleted = OFTrue; } } } /** Removes one item from the set. * @param index Index of the item which shall be removed from the set. */ virtual void RemoveByIndex( unsigned int index ) { // do something only if the given index is not out of range if( index < OFSet::num ) { // delete item with given index delete OFSet::items[index]; // and - so that there are no holes in the array - move the last // item to the array field from which the item was deleted; // only do so in case we did _not_ delete the last item if( index != OFSet::num - 1 ) { OFSet::items[index] = OFSet::items[OFSet::num-1]; OFSet::items[OFSet::num-1] = NULL; } else OFSet::items[index] = NULL; // reduce counter OFSet::num--; } } /** Tries to find a given object in the set. In case the specified object could * be found, a pointer to the corresponding element within the set is returned; * in case the specified object could not be found, NULL will be returned. * @param item Search pattern. * @return Pointer to the corresponding element within the set or NULL. */ virtual T *Find( const T &item ) const { unsigned int i; OFBool itemFound = OFFalse; for( i=0 ; i::num && !itemFound ; i++ ) { if( *OFSet::items[i] == item ) itemFound = OFTrue; } if( itemFound ) return( OFSet::items[i-1] ); else return( NULL ); } /** Determines if a certain item is contained in the set. * @param item - Item which shall be looked for. * @return OFTrue, if item is contained in the set, OFFalse otherwise. */ virtual OFBool Contains( const T &item ) const { OFBool itemFound = OFFalse; for( unsigned int i=0 ; i::num && !itemFound ; i++ ) { if( *OFSet::items[i] == item ) itemFound = OFTrue; } return( itemFound ); } /** Determines if this is an actual superset of other, i.e. * if this completely contains other and furthermore has * additional elements. * @param other - Set which shall be compared with this. * @return OFTrue if this is a superset of other, OFFalse otherwise. */ virtual OFBool IsSupersetOf( const OFUnorderedSet &other ) const { // if this contains less or the same amount of items than other, return OFFalse if( OFSet::num <= other.num ) return( OFFalse ); // initialize result with OFTrue OFBool result = OFTrue; // make a copy of this OFUnorderedSet s = *this; // as long as result is OFTrue go through all items in other for( unsigned int i=0 ; i &other ) const { return( other.IsSupersetOf( *this ) ); } /** Determines the union of the two sets this and other, i.e. the set * containing all items which can be found either in this or in other, * and returns the resulting new set. * @param other Second parameter for union. * @return New set. */ OFUnorderedSet Union( const OFUnorderedSet &other ) const { // initialize result set OFUnorderedSet resultSet = *this; // insert other set into result set resultSet.Insert( other ); // return result set return( resultSet ); } /** Determines the intersection of the two sets this and other, i.e. the set * containing all items which can be found in both this and other, and * returns the resulting new set. * @param other Second parameter for intersection. * @return New set. */ OFUnorderedSet Intersection( const OFUnorderedSet &other ) const { // initialize result set OFUnorderedSet resultSet; // make a copy of other OFUnorderedSet s = other; // go through all items in this for( unsigned int i=0 ; i< OFSet::num ; i++ ) { // if s contains the current item if( s.Contains( *OFSet::items[i] ) ) { // insert the item into the result set resultSet.Insert( *OFSet::items[i] ); // and remove the item from s so that it will not be // considered again in a later call to s.Contains() s.Remove( *OFSet::items[i] ); } } // return result set return( resultSet ); } /** Determines the difference this - other, i.e. the set containing all * the items found in this but not in other, and returns the resulting * new set. * @param other Second parameter for difference. * @return New set. */ OFUnorderedSet Difference( const OFUnorderedSet &other ) const { // initialize result set OFUnorderedSet resultSet; // make a copy of other OFUnorderedSet s = other; // go through all items in this for( unsigned int i=0 ; i< OFSet::num ; i++ ) { // if s does not contain the current item if( !s.Contains( *OFSet::items[i] ) ) { // insert the item into the result set resultSet.Insert( *OFSet::items[i] ); } else { // else remove the item from s so that it will not be // considered again in a later call to s.Contains() s.Remove( *OFSet::items[i] ); } } // return result set return( resultSet ); } /** Determines the symmetric difference of this and other, i.e. the set * containing all the items which can be found either in this or in other * but not in the intersection of this and other, and returns the resulting * new set. * @param other Second parameter for symmetric difference. * @return New set. */ OFUnorderedSet SymmetricDifference( const OFUnorderedSet &other ) const { // determine s1 = this - other OFUnorderedSet s1 = (*this).Difference( other ); // determine s2 = other - this OFUnorderedSet s2 = other.Difference( *this ); // determine the union of s1 and s2 OFUnorderedSet resultSet = s1.Union( s2 ); // return result set return( resultSet ); } }; #endif