//+------------------------------------------------------------------+ //| SortedList.mqh | //| Copyright 2000-2025, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #include #include #include "RedBlackTree.mqh" #include "HashSet.mqh" //+------------------------------------------------------------------+ //| Class CSortedSet. | //| Usage: Represents a collection of objects that is maintained in | //| sorted order. | //+------------------------------------------------------------------+ template class CSortedSet: public ISet { protected: CRedBlackTree*m_tree; public: CSortedSet(void); CSortedSet(IComparer*comparer); CSortedSet(ICollection*collection); CSortedSet(ICollection*collection,IComparer*comparer); CSortedSet(T &array[]); CSortedSet(T &array[],IComparer*comparer); ~CSortedSet(void); //--- methods of filling data bool Add(T value) { return(m_tree.Add(value)); } //--- methods of access to protected data int Count(void) { return(m_tree.Count()); } bool Contains(T item) { return(m_tree.Contains(item)); } IComparer *Comparer(void) const { return(m_tree.Comparer()); } bool TryGetMin(T &min) { return(m_tree.TryGetMin(min)); } bool TryGetMax(T &max) { return(m_tree.TryGetMax(max)); } //--- methods of copy data from collection int CopyTo(T &dst_array[],const int dst_start=0); //--- methods of cleaning and deleting void Clear(void) { m_tree.Clear(); } bool Remove(T item) { return(m_tree.Remove(item)); } //--- methods of changing sets void ExceptWith(ICollection*collection); void ExceptWith(T &array[]); void IntersectWith(ICollection*collection); void IntersectWith(T &array[]); void SymmetricExceptWith(ICollection*collection); void SymmetricExceptWith(T &array[]); void UnionWith(ICollection*collection); void UnionWith(T &array[]); //--- methods for determining the relationship between sets bool IsProperSubsetOf(ICollection*collection); bool IsProperSubsetOf(T &array[]); bool IsProperSupersetOf(ICollection*collection); bool IsProperSupersetOf(T &array[]); bool IsSubsetOf(ICollection*collection); bool IsSubsetOf(T &array[]); bool IsSupersetOf(ICollection*collection); bool IsSupersetOf(T &array[]); bool Overlaps(ICollection*collection); bool Overlaps(T &array[]); bool SetEquals(ICollection*collection); bool SetEquals(T &array[]); //--- methods for working with an ordered set bool GetViewBetween(T &array[],T lower_value,T upper_value); bool GetReverse(T &array[]); }; //+------------------------------------------------------------------+ //| Initializes a new instance of the CSortedSet class that is | //| empty and uses the default equality comparer for the set type. | //+------------------------------------------------------------------+ template CSortedSet::CSortedSet(void) { m_tree=new CRedBlackTree(); } //+------------------------------------------------------------------+ //| Initializes a new instance of the CSortedSet class that is | //| empty and uses the specified equality comparer for the set type. | //+------------------------------------------------------------------+ template CSortedSet::CSortedSet(IComparer*comparer) { m_tree=new CRedBlackTree(comparer); } //+------------------------------------------------------------------+ //| Initializes a new instance of the CSortedSet class that uses | //| the default equality comparer for the set type, contains elements| //| copied from the specified collection, and has sufficient capacity| //| to accommodate the number of elements copied. | //+------------------------------------------------------------------+ template CSortedSet::CSortedSet(ICollection*collection) { m_tree=new CRedBlackTree(collection); } //+------------------------------------------------------------------+ //| Initializes a new instance of the CSortedSet class that uses | //| the specified equality comparer for the set type, contains | //| elements copied from the specified collection, and has sufficient| //| capacity to accommodate the number of elements copied. | //+------------------------------------------------------------------+ template CSortedSet::CSortedSet(ICollection*collection,IComparer*comparer) { m_tree=new CRedBlackTree(collection,comparer); } //+------------------------------------------------------------------+ //| Initializes a new instance of the CSortedSet class that uses | //| the default equality comparer for the set type, contains | //| elements copied from the specified array, and has sufficient | //| capacity to accommodate the number of elements copied. | //+------------------------------------------------------------------+ template CSortedSet::CSortedSet(T &array[]) { m_tree=new CRedBlackTree(array); } //+------------------------------------------------------------------+ //| Initializes a new instance of the CSortedSet class that uses | //| the specified equality comparer for the set type, contains | //| elements copied from the specified array, and has sufficient | //| capacity to accommodate the number of elements copied. | //+------------------------------------------------------------------+ template CSortedSet::CSortedSet(T &array[],IComparer*comparer) { m_tree=new CRedBlackTree(array,comparer); } //+------------------------------------------------------------------+ //| Destructor. | //+------------------------------------------------------------------+ template CSortedSet::~CSortedSet(void) { delete m_tree; } //+------------------------------------------------------------------+ //| Copies a range of elements from the set to a compatible | //| one-dimensional array. | //+------------------------------------------------------------------+ template int CSortedSet::CopyTo(T &dst_array[],const int dst_start=0) { return(m_tree.CopyTo(dst_array, dst_start)); } //+------------------------------------------------------------------+ //| Removes all elements in the specified collection from the current| //| set. | //+------------------------------------------------------------------+ template void CSortedSet::ExceptWith(ICollection*collection) { //--- check collection if(CheckPointer(collection)==POINTER_INVALID) return; //--- check tree count if(m_tree.Count()==0) return; //--- special case if collection is this //--- a set minus itself is the empty set if(collection==GetPointer(this)) { Clear(); return; } //--- copy collection to array T array[]; int size=collection.CopyTo(array); //--- find max and min value T max; T min; //--- get comaprer IComparer*comparer=Comparer(); if(!m_tree.TryGetMax(max)) return; if(!m_tree.TryGetMin(min)) return; //--- remove elements for(int i=0; i0) && Contains(item)) m_tree.Remove(item); } } //+------------------------------------------------------------------+ //| Removes all elements in the specified array from the current set.| //+------------------------------------------------------------------+ template void CSortedSet::ExceptWith(T &array[]) { //--- check tree count if(m_tree.Count()==0) return; //--- get array size int size=ArraySize(array); //--- find max and min value T max; T min; //--- get comparer IComparer*comparer=Comparer(); if(!m_tree.TryGetMax(max)) return; if(!m_tree.TryGetMin(min)) return; //--- remove elements for(int i=0; i0) && Contains(item)) m_tree.Remove(item); } } //+------------------------------------------------------------------+ //| Modifies the current set to contain only elements that are | //| present in that object and in the specified collection. | //+------------------------------------------------------------------+ template void CSortedSet::IntersectWith(ICollection*collection) { //--- check collection if(CheckPointer(collection)==POINTER_INVALID) return; //--- check tree count if(m_tree.Count()==0) return; //--- special case if collection is this //--- a set minus itself is the empty set if(collection==GetPointer(this)) return; //--- copy collection to array T array[]; int size=collection.CopyTo(array); //--- create emty tree CRedBlackTree*tree=new CRedBlackTree(); //--- store values conatin in tree and array for(int i=0; i void CSortedSet::IntersectWith(T &array[]) { //--- check tree count if(m_tree.Count()==0) return; //--- get array size int size=ArraySize(array); //--- create emty tree CRedBlackTree*tree=new CRedBlackTree(); //--- store values conatin in tree and array for(int i=0; i void CSortedSet::SymmetricExceptWith(ICollection*collection) { //--- check collection if(CheckPointer(collection)==POINTER_INVALID) return; //--- check collection count if(collection.Count()==0) return; //--- check tree count if(m_tree.Count()==0) { UnionWith(collection); return; } //--- special case if collection is this //--- a set minus itself is the empty set if(collection==GetPointer(this)) { Clear(); return; } //--- copy colleaction to array T array[]; int size=collection.CopyTo(array); //--- get comparer IComparer*comparer=m_tree.Comparer(); //--- sort array Introsortsort; ArrayCopy(sort.keys,array); sort.comparer=comparer; sort.Sort(0, size); ArrayCopy(array,sort.keys); //--- modify tree T last=array[0]; for(int i=0; i=size) break; if(m_tree.Contains(array[i])) m_tree.Remove(array[i]); else m_tree.Add(array[i]); last=array[i]; } } //+------------------------------------------------------------------+ //| Modifies the current set to contain only elements that are | //| present either in that set or in the specified array, but not | //| both. | //+------------------------------------------------------------------+ template void CSortedSet::SymmetricExceptWith(T &array[]) { //--- check array size if(ArraySize(array)==0) return; //--- check tree count if(m_tree.Count()==0) { UnionWith(array); return; } //--- get size int size=ArraySize(array); //--- get comparer IComparer*comparer=m_tree.Comparer(); //--- sort array Introsortsort; ArrayCopy(sort.keys,array); sort.comparer=comparer; sort.Sort(0, size); ArrayReverse(sort.keys,0,ArraySize(sort.keys)); //--- modify tree T last=sort.keys[0]; for(int i=0; i=size) break; if(m_tree.Contains(sort.keys[i])) m_tree.Remove(sort.keys[i]); else m_tree.Add(sort.keys[i]); last=sort.keys[i]; } } //+------------------------------------------------------------------+ //| Modifies the current set to contain all elements that are present| //| in itself, the specified collection, or both. | //+------------------------------------------------------------------+ template void CSortedSet::UnionWith(ICollection*collection) { //--- check collection if(CheckPointer(collection)==POINTER_INVALID) return; //--- copy all elements from collecton to array T array[]; int size=collection.CopyTo(array); //--- add all elemets from array to set for(int i=0; i void CSortedSet::UnionWith(T &array[]) { //--- get array size int size=ArraySize(array); //--- add all elemets from array to set for(int i=0; i bool CSortedSet::IsProperSubsetOf(ICollection*collection) { //--- check collection if(CheckPointer(collection)==POINTER_INVALID) return(false); //--- check tree count if(m_tree.Count()==0) return(collection.Count() > 0); //--- check collection is set CHashSet*ptr_set=dynamic_cast*>(collection); if(CheckPointer(ptr_set)!=POINTER_INVALID) { return(ptr_set.IsProperSupersetOf(m_tree)); } else { //--- create a set based on a specified collection CHashSetset(collection); return(set.IsProperSupersetOf(m_tree)); } } //+------------------------------------------------------------------+ //| Determines whether a set is a proper subset of the specified | //| array. | //+------------------------------------------------------------------+ template bool CSortedSet::IsProperSubsetOf(T &array[]) { if(m_tree.Count()==0) return(ArraySize(array) > 0); //--- create a set based on a specified array CHashSetset(array); if(m_tree.Count()>=set.Count()) return(false); return(set.IsProperSupersetOf(m_tree)); } //+------------------------------------------------------------------+ //| Determines whether a set is a proper superset of the specified | //| collection. | //+------------------------------------------------------------------+ template bool CSortedSet::IsProperSupersetOf(ICollection*collection) { //--- check collection if(CheckPointer(collection)==POINTER_INVALID) return(m_tree.Count()>0); //--- check tree count if(m_tree.Count()==0) return(false); //--- check collection count if(collection.Count()==0) return(true); //--- check collection is set CHashSet*ptr_set=dynamic_cast*>(collection); if(CheckPointer(ptr_set)!=POINTER_INVALID) { return(ptr_set.IsProperSubsetOf(m_tree)); } else { //--- create a set based on a specified collection CHashSetset(collection); return(set.IsProperSubsetOf(m_tree)); } } //+------------------------------------------------------------------+ //| Determines whether a set is a proper superset of the specified | //| array. | //+------------------------------------------------------------------+ template bool CSortedSet::IsProperSupersetOf(T &array[]) { if(m_tree.Count()==0) return(false); if(ArraySize(array)==0) return(true); //--- create a set based on a specified array CHashSetset(array); return(set.IsProperSubsetOf(m_tree)); } //+------------------------------------------------------------------+ //| Determines whether a set is a subset of the specified collection.| //+------------------------------------------------------------------+ template bool CSortedSet::IsSubsetOf(ICollection*collection) { //--- cehck collection if(CheckPointer(collection)==POINTER_INVALID) return(m_tree.Count()==0); //--- check tree count if(m_tree.Count()==0) return(true); //--- check collection is set CHashSet*ptr_set=dynamic_cast*>(collection); if(CheckPointer(ptr_set)==POINTER_DYNAMIC) { return(ptr_set.IsProperSupersetOf(m_tree)); } else { //--- create a set based on a specified collection CHashSetset(collection); return(set.IsProperSupersetOf(m_tree)); } } //+------------------------------------------------------------------+ //| Determines whether a set is a subset of the specified array. | //+------------------------------------------------------------------+ template bool CSortedSet::IsSubsetOf(T &array[]) { //--- check tree count if(m_tree.Count()==0) return(true); //--- create a set based on a specified array CHashSetset(array); if(m_tree.Count()>set.Count()) return(false); return(set.IsProperSupersetOf(m_tree)); } //+------------------------------------------------------------------+ //| Determines whether a set is a superset of the specified | //| collection. | //+------------------------------------------------------------------+ template bool CSortedSet::IsSupersetOf(ICollection*collection) { //--- check collection if(CheckPointer(collection)==POINTER_INVALID) return(m_tree.Count()>=0); //--- check collection count if(collection.Count()==0) return(true); //--- check collection is set CHashSet*ptr_set=dynamic_cast*>(collection); if(CheckPointer(ptr_set)!=POINTER_INVALID) { return(ptr_set.IsSupersetOf(m_tree)); } else { //--- create a set based on a specified collection CHashSetset(collection); return(set.IsSupersetOf(m_tree)); } } //+------------------------------------------------------------------+ //| Determines whether a set is a superset of the specified array. | //+------------------------------------------------------------------+ template bool CSortedSet::IsSupersetOf(T &array[]) { //--- check array size if(ArraySize(array)==0) return(true); //--- create a set based on a specified array CHashSetset(array); return(set.IsSupersetOf(m_tree)); } //+------------------------------------------------------------------+ //| Determines whether the current set and a specified collection | //| share common elements. | //+------------------------------------------------------------------+ template bool CSortedSet::Overlaps(ICollection*collection) { //--- check collection if(CheckPointer(collection)==POINTER_INVALID) return(false); //--- check tree count if(m_tree.Count()==0) return(false); //--- check collection count if(collection.Count()==0) return(false); //--- check collection is set CHashSet*ptr_set=dynamic_cast*>(collection); if(CheckPointer(ptr_set)!=POINTER_INVALID) { return(ptr_set.Overlaps(m_tree)); } else { //--- create a set based on a specified collection CHashSetset(collection); return(set.Overlaps(m_tree)); } } //+------------------------------------------------------------------+ //| Determines whether the current set and a specified array share | //| common elements. | //+------------------------------------------------------------------+ template bool CSortedSet::Overlaps(T &array[]) { //--- check tree count if(m_tree.Count()==0) return(false); //--- check array size if(ArraySize(array)==0) return(false); //--- convert array to set CHashSetset(array); return(set.Overlaps(m_tree)); } //+------------------------------------------------------------------+ //| Determines whether a set and the specified collection contain the| //| same elements. | //+------------------------------------------------------------------+ template bool CSortedSet::SetEquals(ICollection*collection) { if(CheckPointer(collection)==POINTER_INVALID) return(false); //--- get array from collection T array[]; collection.CopyTo(array); //--- check current set is equal specified array return SetEquals(array); } //+------------------------------------------------------------------+ //| Determines whether a set and the specified array contain the same| //| elements. | //+------------------------------------------------------------------+ template bool CSortedSet::SetEquals(T &array[]) { //--- try find all elements in the tree for(int i=0; i to array. | //+------------------------------------------------------------------+ template bool CSortedSet::GetViewBetween(T &array[],T lower_value,T upper_value) { //--- get comparer IComparer*comparer=m_tree.Comparer(); if(comparer.Compare(lower_value,upper_value)>0) return(false); //--- copy all element from tree to array T buff[]; int size=m_tree.CopyTo(buff); //--- check range if(size==0 || comparer.Compare(buff[0],upper_value)>0 || comparer.Compare(buff[size-1],lower_value)<0) return(false); //--- find first element greater than lower_value int index_lower=0; while(index_lower0 && comparer.Compare(buff[index_upper],upper_value)>0) index_upper--; //--- check indices if(index_lower>index_upper) return(false); //--- copy view between lower_value and upper_value to array return(ArrayCopy(array,buff,0,index_lower,index_upper-index_lower+1)>=0); } //+------------------------------------------------------------------+ //| Copy the CSortedSet in reverse order to array. | //+------------------------------------------------------------------+ template bool CSortedSet::GetReverse(T &array[]) { int size=m_tree.CopyTo(array); return ArrayReverse(array,0,size); } //+------------------------------------------------------------------+