DYT/Tool/3rdParty_x64/include/dcmtk/ofstd/ofuoset.h
2024-11-22 23:19:31 +08:00

438 lines
13 KiB
C++

/*
*
* 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 T> class OFUnorderedSet : public OFSet<T>
{
protected:
public:
/** Default constructor.
*/
OFUnorderedSet()
: OFSet<T>()
{
}
/** Copy constructor.
* @param src Source object of which this will be a copy.
*/
OFUnorderedSet( const OFUnorderedSet<T> &src )
: OFSet<T>( src )
{
}
/** Destructor.
*/
virtual ~OFUnorderedSet()
{
}
/** operator=.
* @param src Source object whose values will be assigned to this.
* @return Reference to this.
*/
const OFUnorderedSet<T> &operator=( const OFUnorderedSet<T> &src )
{
if( this == &src )
return( *this );
OFSet<T>::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<T> &other ) const
{
// check if both sets contain the same
// amount of items; if not, return OFFalse
if( OFSet<T>::num != other.num )
return( OFFalse );
// initialize result with OFTrue
OFBool result = OFTrue;
// make a copy of this
OFUnorderedSet<T> s = *this;
// as long as result is OFTrue go through all items in other
for( unsigned int i=0 ; i<other.num && result == OFTrue ; i++ )
{
// in case s contains the current item of other
if( s.Contains( *other.items[i] ) )
{
// remove this item from s so that it will not be
// considered again in a later call to s.Contains()
s.Remove( *other.items[i] );
}
// in case s doesn't contain the current item of other the result is OFFalse
else
result = OFFalse;
}
// return result
return( result );
}
/** Determines if two sets are not identical.
* @param other Set which shall be compared with this.
* @return OFTrue if sets are not identical, OFFalse otherwise.
*/
virtual OFBool operator!=( const OFUnorderedSet<T> &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<T>::size == OFSet<T>::num )
this->Resize( OFSet<T>::size * 2 );
// copy item
T *newItem = new T( item );
// insert copy into array
OFSet<T>::items[OFSet<T>::num] = newItem;
// increase counter
OFSet<T>::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<T> &other )
{
// go through all items in other and insert each item into this
for( unsigned int i=0 ; i<other.num ; i++ )
Insert( *other.items[i] );
}
/** Removes one item from the set.
* @param item Item which shall be removed from the set.
*/
virtual void Remove( const T &item )
{
// so far, nothing was deleted
OFBool itemDeleted = OFFalse;
// go through all items
for( unsigned int i=0 ; i<OFSet<T>::num && !itemDeleted ; i++ )
{
// if current item is the one which shall be deleted
if( *OFSet<T>::items[i] == item )
{
// delete item
delete OFSet<T>::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<T>::num - 1 )
{
OFSet<T>::items[i] = OFSet<T>::items[OFSet<T>::num-1];
OFSet<T>::items[OFSet<T>::num-1] = NULL;
}
else
OFSet<T>::items[i] = NULL;
// reduce counter
OFSet<T>::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<T>::num )
{
// delete item with given index
delete OFSet<T>::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<T>::num - 1 )
{
OFSet<T>::items[index] = OFSet<T>::items[OFSet<T>::num-1];
OFSet<T>::items[OFSet<T>::num-1] = NULL;
}
else
OFSet<T>::items[index] = NULL;
// reduce counter
OFSet<T>::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<OFSet<T>::num && !itemFound ; i++ )
{
if( *OFSet<T>::items[i] == item )
itemFound = OFTrue;
}
if( itemFound )
return( OFSet<T>::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<OFSet<T>::num && !itemFound ; i++ )
{
if( *OFSet<T>::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<T> &other ) const
{
// if this contains less or the same amount of items than other, return OFFalse
if( OFSet<T>::num <= other.num )
return( OFFalse );
// initialize result with OFTrue
OFBool result = OFTrue;
// make a copy of this
OFUnorderedSet<T> s = *this;
// as long as result is OFTrue go through all items in other
for( unsigned int i=0 ; i<other.num && result == OFTrue ; i++ )
{
// in case s contains the current item of other
if( s.Contains( *other.items[i] ) )
{
// remove this item from s so that it will not be
// considered again in a later call to s.Contains()
s.Remove( *other.items[i] );
}
// in case s does not contain the current item of other the result is OFFalse
else
result = OFFalse;
}
// return result
return( result );
}
/** Determines if this is an actual subset of other, i.e.
* if this is completely contained in other and other
* furthermore has additional elements.
* @param other - Set which shall be compared with this.
* @return OFTrue if this is a subset of other, OFFalse otherwise.
*/
virtual OFBool IsSubsetOf( const OFUnorderedSet<T> &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<T> Union( const OFUnorderedSet<T> &other ) const
{
// initialize result set
OFUnorderedSet<T> 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<T> Intersection( const OFUnorderedSet<T> &other ) const
{
// initialize result set
OFUnorderedSet<T> resultSet;
// make a copy of other
OFUnorderedSet<T> s = other;
// go through all items in this
for( unsigned int i=0 ; i< OFSet<T>::num ; i++ )
{
// if s contains the current item
if( s.Contains( *OFSet<T>::items[i] ) )
{
// insert the item into the result set
resultSet.Insert( *OFSet<T>::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<T>::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<T> Difference( const OFUnorderedSet<T> &other ) const
{
// initialize result set
OFUnorderedSet<T> resultSet;
// make a copy of other
OFUnorderedSet<T> s = other;
// go through all items in this
for( unsigned int i=0 ; i< OFSet<T>::num ; i++ )
{
// if s does not contain the current item
if( !s.Contains( *OFSet<T>::items[i] ) )
{
// insert the item into the result set
resultSet.Insert( *OFSet<T>::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<T>::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<T> SymmetricDifference( const OFUnorderedSet<T> &other ) const
{
// determine s1 = this - other
OFUnorderedSet<T> s1 = (*this).Difference( other );
// determine s2 = other - this
OFUnorderedSet<T> s2 = other.Difference( *this );
// determine the union of s1 and s2
OFUnorderedSet<T> resultSet = s1.Union( s2 );
// return result set
return( resultSet );
}
};
#endif