//+------------------------------------------------------------------+ //| SortedMap.mqh | //| Copyright 2000-2025, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #include #include #include #include #include "HashMap.mqh" #include "SortedSet.mqh" //+------------------------------------------------------------------+ //| Class CSortedMap. | //| Usage: Represents a collection of key/value pairs that are sorted| //| on the key. | //+------------------------------------------------------------------+ template class CSortedMap: public IMap { protected: CRedBlackTree*>*m_tree; IComparer*m_comparer; bool m_delete_comparer; public: CSortedMap(void); CSortedMap(IComparer*comparer); CSortedMap(IMap*map); CSortedMap(IMap*map,IComparer*comparer); ~CSortedMap(void); //--- methods of filling data bool Add(CKeyValuePair*value) { return m_tree.Add(value); } bool Add(TKey key,TValue value); //--- methods of access to protected data int Count(void) { return m_tree.Count(); } bool Contains(CKeyValuePair*item) { return m_tree.Contains(item); } bool Contains(TKey key,TValue value); bool ContainsKey(TKey key); bool ContainsValue(TValue value); IComparer *Comparer(void) const { return(m_comparer); } //--- methods of copy data from collection int CopyTo(CKeyValuePair*&dst_array[],const int dst_start=0); int CopyTo(TKey &dst_keys[],TValue &dst_values[],const int dst_start=0); //--- methods of cleaning and deleting void Clear(void); bool Remove(CKeyValuePair*item) { return m_tree.Remove(item); } bool Remove(TKey key); //--- method of access to the data bool TryGetValue(TKey key,TValue &value); bool TrySetValue(TKey key,TValue value); private: static void ClearNodes(CRedBlackTreeNode*>*node); }; //+------------------------------------------------------------------+ //| Initializes a new instance of the CSortedMap class | //| that is empty, has the default initial capacity, and uses the | //| default comparer for the key type. | //+------------------------------------------------------------------+ template CSortedMap::CSortedMap(void) { //--- use default comaprer m_comparer=new CDefaultComparer(); m_delete_comparer=true; m_tree=new CRedBlackTree*>(new CKeyValuePairComparer(m_comparer)); } //+------------------------------------------------------------------+ //| Initializes a new instance of the CSortedMap class | //| that is empty, has the default initial capacity, and uses the | //| specified IComparer. | //+------------------------------------------------------------------+ template CSortedMap::CSortedMap(IComparer*comparer) { //--- check comaprer if(CheckPointer(comparer)==POINTER_INVALID) { //--- use default comaprer m_comparer=new CDefaultComparer(); m_delete_comparer=true; } else { //--- use specified comaprer m_comparer=comparer; m_delete_comparer=false; } m_tree=new CRedBlackTree*>(new CKeyValuePairComparer(m_comparer)); } //+------------------------------------------------------------------+ //| Initializes a new instance of the CSortedMap class | //| that contains elements copied from the specified | //| IMap and uses the default comparer for the key type.| //+------------------------------------------------------------------+ template CSortedMap::CSortedMap(IMap*map) { //--- use default comaprer m_comparer=new CDefaultComparer(); m_delete_comparer=true; m_tree=new CRedBlackTree*>(map,new CKeyValuePairComparer(m_comparer)); } //+------------------------------------------------------------------+ //| Initializes a new instance of the CSortedMap class | //| that contains elements copied from the specified | //| IMap and uses the specified IComparer. | //+------------------------------------------------------------------+ template CSortedMap::CSortedMap(IMap*map,IComparer*comparer) { //--- check comaprer if(CheckPointer(comparer)==POINTER_INVALID) { //--- use default comaprer m_comparer=new CDefaultComparer(); m_delete_comparer=true; } else { //--- use specified comaprer m_comparer=comparer; m_delete_comparer=false; } m_tree=new CRedBlackTree*>(map,new CKeyValuePairComparer(m_comparer)); } //+------------------------------------------------------------------+ //| Destructor. | //+------------------------------------------------------------------+ template CSortedMap::~CSortedMap(void) { //--- delete comparer if(m_delete_comparer) delete m_comparer; //--- delete tree comparer delete m_tree.Comparer(); //--- delete nodes values ClearNodes(m_tree.Root()); //--- delete tree and nodes delete m_tree; } //+------------------------------------------------------------------+ //| Walk all nodes of tree and delete their value. | //+------------------------------------------------------------------+ template static void CSortedMap::ClearNodes(CRedBlackTreeNode*>*node) { //--- check node if(CheckPointer(node)==POINTER_INVALID) return; //--- walk of a right subtree if(!node.Right().IsLeaf()) ClearNodes(node.Right()); //--- delete value delete node.Value(); //--- walk of a left subtree if(!node.Left().IsLeaf()) ClearNodes(node.Left()); } //+------------------------------------------------------------------+ //| Adds the specified key and value to the map. | //+------------------------------------------------------------------+ template bool CSortedMap::Add(TKey key,TValue value) { //--- create pair CKeyValuePair*pair=new CKeyValuePair(key,value); //--- add pair to tree bool success=m_tree.Add(pair); //--- if addition was not successful delte pair if(!success) delete pair; return(success); } //+------------------------------------------------------------------+ //| Determines whether the map contains the specified key with value.| //+------------------------------------------------------------------+ template bool CSortedMap::Contains(TKey key,TValue value) { //--- find node with specified key CKeyValuePairpair(key,NULL); CRedBlackTreeNode*>*node=m_tree.Find(GetPointer(pair)); //--- create value comparer CDefaultEqualityComparercomaprer; //--- determine whether the finding node contains specified value if(CheckPointer(node)!=POINTER_INVALID && comaprer.Equals(value,node.Value().Value())) return(true); return(false); } //+------------------------------------------------------------------+ //| Determines whether the map contains the specified key. | //+------------------------------------------------------------------+ template bool CSortedMap::ContainsKey(TKey key) { //--- crete pair CKeyValuePairpair(key,NULL); //--- determines whether the tree contains the pair. return m_tree.Contains(GetPointer(pair)); } //+------------------------------------------------------------------+ //| Determines whether the map contains the specified value. | //+------------------------------------------------------------------+ template bool CSortedMap::ContainsValue(TValue value) { //--- copy all pairs in array CKeyValuePair*array[]; int count=m_tree.CopyTo(array); //--- create value comparer CDefaultEqualityComparercomaprer; //--- determines whether the array contains the specified value for(int i=0; i int CSortedMap::CopyTo(CKeyValuePair*&dst_array[],const int dst_start=0) { int result=m_tree.CopyTo(dst_array,dst_start); if(result>0) { //--- create clones for each pair for(int i=0; i int CSortedMap::CopyTo(TKey &dst_keys[],TValue &dst_values[],const int dst_start=0) { //--- create array and copy all values from tree to there CKeyValuePair*array[]; int count=m_tree.CopyTo(array); //--- check real cout if(count>0) { //--- resize keys array if(dst_start+count>ArraySize(dst_keys)) ArrayResize(dst_keys,dst_start+count); //--- resize values array if(dst_start+count>ArraySize(dst_values)) ArrayResize(dst_values,MathMin(ArraySize(dst_keys),dst_start+count)); //--- start copy int index=0; while(index void CSortedMap::Clear(void) { //--- check count if(m_tree.Count()>0) { //--- delete nodes values ClearNodes(m_tree.Root()); //--- claer th tree m_tree.Clear(); } } //+------------------------------------------------------------------+ //| Removes the value with the specified key from the map. | //+------------------------------------------------------------------+ template bool CSortedMap::Remove(TKey key) { //--- create pair with specified key CKeyValuePairpair(key,NULL); //--- find node CRedBlackTreeNode*>*node=m_tree.Find(GetPointer(pair)); //--- check node if(CheckPointer(node)!=POINTER_INVALID) { CKeyValuePair*real_pair=node.Value(); //--- remove node from tree if(m_tree.Remove(node)) { //--- check and delete node value if(CheckPointer(real_pair)==POINTER_DYNAMIC) delete real_pair; return(true); } } return(false); } //+------------------------------------------------------------------+ //| Gets the value associated with the specified key. | //+------------------------------------------------------------------+ template bool CSortedMap::TryGetValue(TKey key,TValue &value) { //--- create pair with specified key CKeyValuePairpair(key,NULL); //--- find node with specified pair in the tree CRedBlackTreeNode*>*node=m_tree.Find(GetPointer(pair)); //--- check node if(CheckPointer(node)==POINTER_INVALID) return(false); //--- get value value=node.Value().Value(); return(true); } //+------------------------------------------------------------------+ //| Sets the value associated with the specified key. | //+------------------------------------------------------------------+ template bool CSortedMap::TrySetValue(TKey key,TValue value) { //--- create pair with specified key CKeyValuePairpair(key,NULL); //--- find node with specified pair in the tree CRedBlackTreeNode*>*node=m_tree.Find(GetPointer(pair)); //--- check node if(CheckPointer(node)==POINTER_INVALID) return(false); //--- set value node.Value().Value(value); return(true); } //+------------------------------------------------------------------+