Add files via upload

This commit is contained in:
amirghadiri1987
2025-02-07 19:03:59 +03:30
committed by GitHub
parent fbeb7771c7
commit df71b67cc0
37 changed files with 23512 additions and 0 deletions
+182
View File
@@ -0,0 +1,182 @@
//+------------------------------------------------------------------+
//| Array.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Object.mqh>
//+------------------------------------------------------------------+
//| Class CArray |
//| Purpose: Base class of dynamic arrays. |
//| Derives from class CObject. |
//+------------------------------------------------------------------+
class CArray : public CObject
{
protected:
int m_step_resize; // increment size of the array
int m_data_total; // number of elements
int m_data_max; // maximmum size of the array without memory reallocation
int m_sort_mode; // mode of array sorting
public:
CArray(void);
~CArray(void);
//--- methods of access to protected data
int Step(void) const { return(m_step_resize); }
bool Step(const int step);
int Total(void) const { return(m_data_total); }
int Available(void) const { return(m_data_max-m_data_total); }
int Max(void) const { return(m_data_max); }
bool IsSorted(const int mode=0) const { return(m_sort_mode==mode); }
int SortMode(void) const { return(m_sort_mode); }
//--- cleaning method
void Clear(void) { m_data_total=0; }
//--- methods for working with files
virtual bool Save(const int file_handle);
virtual bool Load(const int file_handle);
//--- sorting method
void Sort(const int mode=0);
protected:
virtual void QuickSort(int beg,int end,const int mode=0) { m_sort_mode=-1; }
//--- templates for methods of searching for minimum and maximum
template<typename T>
int Minimum(const T &data[],const int start,const int count) const;
template<typename T>
int Maximum(const T &data[],const int start,const int count) const;
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CArray::CArray(void) : m_step_resize(16),
m_data_total(0),
m_data_max(0),
m_sort_mode(-1)
{
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CArray::~CArray(void)
{
}
//+------------------------------------------------------------------+
//| Method Set for variable m_step_resize |
//+------------------------------------------------------------------+
bool CArray::Step(const int step)
{
//--- check
if(step>0)
{
m_step_resize=step;
return(true);
}
//--- failure
return(false);
}
//+------------------------------------------------------------------+
//| Sorting an array in ascending order |
//+------------------------------------------------------------------+
void CArray::Sort(const int mode)
{
//--- check
if(IsSorted(mode))
return;
m_sort_mode=mode;
if(m_data_total<=1)
return;
//--- sort
QuickSort(0,m_data_total-1,mode);
}
//+------------------------------------------------------------------+
//| Writing header of array to file |
//+------------------------------------------------------------------+
bool CArray::Save(const int file_handle)
{
//--- check handle
if(file_handle!=INVALID_HANDLE)
{
//--- write start marker - 0xFFFFFFFFFFFFFFFF
if(FileWriteLong(file_handle,-1)==sizeof(long))
{
//--- write array type
if(FileWriteInteger(file_handle,Type(),INT_VALUE)==INT_VALUE)
return(true);
}
}
//--- failure
return(false);
}
//+------------------------------------------------------------------+
//| Reading header of array from file |
//+------------------------------------------------------------------+
bool CArray::Load(const int file_handle)
{
//--- check handle
if(file_handle!=INVALID_HANDLE)
{
//--- read and check start marker - 0xFFFFFFFFFFFFFFFF
if(FileReadLong(file_handle)==-1)
{
//--- read and check array type
if(FileReadInteger(file_handle,INT_VALUE)==Type())
return(true);
}
}
//--- failure
return(false);
}
//+------------------------------------------------------------------+
//| Find minimum of array |
//+------------------------------------------------------------------+
template<typename T>
int CArray::Minimum(const T &data[],const int start,const int count) const
{
int real_count;
//--- check for empty array
if(m_data_total<1)
{
SetUserError(ERR_USER_ARRAY_IS_EMPTY);
return(-1);
}
//--- check for start is out of range
if(start<0 || start>=m_data_total)
{
SetUserError(ERR_USER_ITEM_NOT_FOUND);
return(-1);
}
//--- compute count of elements
real_count=(count==WHOLE_ARRAY || start+count>m_data_total) ? m_data_total-start : count;
#ifdef __MQL5__
return(ArrayMinimum(data,start,real_count));
#else
return(ArrayMinimum(data,real_count,start));
#endif
}
//+------------------------------------------------------------------+
//| Find maximum of array |
//+------------------------------------------------------------------+
template<typename T>
int CArray::Maximum(const T &data[],const int start,const int count) const
{
int real_count;
//--- check for empty array
if(m_data_total<1)
{
SetUserError(ERR_USER_ARRAY_IS_EMPTY);
return(-1);
}
//--- check for start is out of range
if(start<0 || start>=m_data_total)
{
SetUserError(ERR_USER_ITEM_NOT_FOUND);
return(-1);
}
//--- compute count of elements
real_count=(count==WHOLE_ARRAY || start+count>m_data_total) ? m_data_total-start : count;
#ifdef __MQL5__
return(ArrayMaximum(data,start,real_count));
#else
return(ArrayMaximum(data,real_count,start));
#endif
}
//+------------------------------------------------------------------+
+771
View File
@@ -0,0 +1,771 @@
//+------------------------------------------------------------------+
//| ArrayChar.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include "Array.mqh"
//+------------------------------------------------------------------+
//| Class CArrayChar. |
//| Purpose: Class of dynamic array of variables |
//| of char or uchar type. |
//| Derives from class CArray. |
//+------------------------------------------------------------------+
class CArrayChar : public CArray
{
protected:
char m_data[]; // data array
public:
CArrayChar(void);
~CArrayChar(void);
//--- method of identifying the object
virtual int Type(void) const { return(TYPE_CHAR); }
//--- methods for working with files
virtual bool Save(const int file_handle);
virtual bool Load(const int file_handle);
//--- methods of managing dynamic memory
bool Reserve(const int size);
bool Resize(const int size);
bool Shutdown(void);
//--- methods of filling the array
bool Add(const char element);
bool AddArray(const char &src[]);
bool AddArray(const CArrayChar *src);
bool Insert(const char element,const int pos);
bool InsertArray(const char &src[],const int pos);
bool InsertArray(const CArrayChar *src,const int pos);
bool AssignArray(const char &src[]);
bool AssignArray(const CArrayChar *src);
//--- method of access to the array
char At(const int index) const;
char operator[](const int index) const { return(At(index)); }
//--- methods of searching for minimum and maximum
int Minimum(const int start,const int count) const { return(CArray::Minimum(m_data,start,count)); }
int Maximum(const int start,const int count) const { return(CArray::Maximum(m_data,start,count)); }
//--- methods of changing
bool Update(const int index,const char element);
bool Shift(const int index,const int shift);
//--- methods of deleting
bool Delete(const int index);
bool DeleteRange(int from,int to);
//--- methods for comparing arrays
bool CompareArray(const char &array[]) const;
bool CompareArray(const CArrayChar *array) const;
//--- methods for working with the sorted array
bool InsertSort(const char element);
int Search(const char element) const;
int SearchGreat(const char element) const;
int SearchLess(const char element) const;
int SearchGreatOrEqual(const char element) const;
int SearchLessOrEqual(const char element) const;
int SearchFirst(const char element) const;
int SearchLast(const char element) const;
int SearchLinear(const char element) const;
protected:
virtual void QuickSort(int beg,int end,const int mode=0);
int QuickSearch(const char element) const;
int MemMove(const int dest,const int src,int count);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CArrayChar::CArrayChar(void)
{
//--- initialize protected data
m_data_max=ArraySize(m_data);
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CArrayChar::~CArrayChar(void)
{
if(m_data_max!=0)
Shutdown();
}
//+------------------------------------------------------------------+
//| Moving the memory within a single array |
//+------------------------------------------------------------------+
int CArrayChar::MemMove(const int dest,const int src,int count)
{
int i;
//--- check parameters
if(dest<0 || src<0 || count<0)
return(-1);
//--- check count
if(src+count>m_data_total)
count=m_data_total-src;
if(count<0)
return(-1);
//--- no need to copy
if(dest==src || count==0)
return(dest);
//--- check data total
if(dest+count>m_data_total)
{
if(m_data_max<dest+count)
return(-1);
m_data_total=dest+count;
}
//--- copy
if(dest<src)
{
//--- copy from left to right
for(i=0;i<count;i++)
m_data[dest+i]=m_data[src+i];
}
else
{
//--- copy from right to left
for(i=count-1;i>=0;i--)
m_data[dest+i]=m_data[src+i];
}
//--- successful
return(dest);
}
//+------------------------------------------------------------------+
//| Request for more memory in an array. Checks if the requested |
//| number of free elements already exists; allocates additional |
//| memory with a given step |
//+------------------------------------------------------------------+
bool CArrayChar::Reserve(const int size)
{
int new_size;
//--- check
if(size<=0)
return(false);
//--- resize array
if(Available()<size)
{
new_size=m_data_max+m_step_resize*(1+(size-Available())/m_step_resize);
if(new_size<0)
//--- overflow occurred when calculating new_size
return(false);
if((m_data_max=ArrayResize(m_data,new_size))==-1)
m_data_max=ArraySize(m_data);
}
//--- result
return(Available()>=size);
}
//+------------------------------------------------------------------+
//| Resizing (with removal of elements on the right) |
//+------------------------------------------------------------------+
bool CArrayChar::Resize(const int size)
{
int new_size;
//--- check
if(size<0)
return(false);
//--- resize array
new_size=m_step_resize*(1+size/m_step_resize);
if(m_data_max!=new_size)
{
if((m_data_max=ArrayResize(m_data,new_size))==-1)
{
m_data_max=ArraySize(m_data);
return(false);
}
}
if(m_data_total>size)
m_data_total=size;
//--- result
return(m_data_max==new_size);
}
//+------------------------------------------------------------------+
//| Complete cleaning of the array with the release of memory |
//+------------------------------------------------------------------+
bool CArrayChar::Shutdown(void)
{
//--- check
if(m_data_max==0)
return(true);
//--- clean
if(ArrayResize(m_data,0)==-1)
return(false);
m_data_total=0;
m_data_max=0;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Adding an element to the end of the array |
//+------------------------------------------------------------------+
bool CArrayChar::Add(const char element)
{
//--- check/reserve elements of array
if(!Reserve(1))
return(false);
//--- add
m_data[m_data_total++]=element;
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Adding an element to the end of the array from another array |
//+------------------------------------------------------------------+
bool CArrayChar::AddArray(const char &src[])
{
int num=ArraySize(src);
//--- check/reserve elements of array
if(!Reserve(num))
return(false);
//--- add
for(int i=0;i<num;i++)
m_data[m_data_total++]=src[i];
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Adding an element to the end of the array from another array |
//+------------------------------------------------------------------+
bool CArrayChar::AddArray(const CArrayChar *src)
{
int num;
//--- check
if(!CheckPointer(src))
return(false);
//--- check/reserve elements of array
num=src.Total();
if(!Reserve(num))
return(false);
//--- add
for(int i=0;i<num;i++)
m_data[m_data_total++]=src.m_data[i];
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Inserting an element in the specified position |
//+------------------------------------------------------------------+
bool CArrayChar::Insert(const char element,const int pos)
{
//--- check/reserve elements of array
if(pos<0 || !Reserve(1))
return(false);
//--- insert
m_data_total++;
if(pos<m_data_total-1)
{
if(MemMove(pos+1,pos,m_data_total-pos-1)<0)
return(false);
m_data[pos]=element;
}
else
m_data[m_data_total-1]=element;
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Inserting elements in the specified position |
//+------------------------------------------------------------------+
bool CArrayChar::InsertArray(const char &src[],const int pos)
{
int num=ArraySize(src);
//--- check/reserve elements of array
if(!Reserve(num))
return(false);
//--- insert
if(MemMove(num+pos,pos,m_data_total-pos)<0)
return(false);
for(int i=0;i<num;i++)
m_data[i+pos]=src[i];
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Inserting elements in the specified position |
//+------------------------------------------------------------------+
bool CArrayChar::InsertArray(const CArrayChar *src,const int pos)
{
int num;
//--- check
if(!CheckPointer(src))
return(false);
//--- check/reserve elements of array
num=src.Total();
if(!Reserve(num))
return(false);
//--- insert
if(MemMove(num+pos,pos,m_data_total-pos)<0)
return(false);
for(int i=0;i<num;i++)
m_data[i+pos]=src.m_data[i];
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Assignment (copying) of another array |
//+------------------------------------------------------------------+
bool CArrayChar::AssignArray(const char &src[])
{
int num=ArraySize(src);
//--- check/reserve elements of array
Clear();
if(m_data_max<num)
{
if(!Reserve(num))
return(false);
}
else
Resize(num);
//--- copy array
for(int i=0;i<num;i++)
{
m_data[i]=src[i];
m_data_total++;
}
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Assignment (copying) of another array |
//+------------------------------------------------------------------+
bool CArrayChar::AssignArray(const CArrayChar *src)
{
int num;
//--- check
if(!CheckPointer(src))
return(false);
//--- check/reserve elements of array
num=src.m_data_total;
Clear();
if(m_data_max<num)
{
if(!Reserve(num))
return(false);
}
else
Resize(num);
//--- copy array
for(int i=0;i<num;i++)
{
m_data[i]=src.m_data[i];
m_data_total++;
}
m_sort_mode=src.SortMode();
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Access to data in the specified position |
//+------------------------------------------------------------------+
char CArrayChar::At(const int index) const
{
//--- check
if(index<0 || index>=m_data_total)
return(CHAR_MAX);
//--- result
return(m_data[index]);
}
//+------------------------------------------------------------------+
//| Updating element in the specified position |
//+------------------------------------------------------------------+
bool CArrayChar::Update(const int index,const char element)
{
//--- check
if(index<0 || index>=m_data_total)
return(false);
//--- update
m_data[index]=element;
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Moving element from the specified position |
//| on the specified shift |
//+------------------------------------------------------------------+
bool CArrayChar::Shift(const int index,const int shift)
{
char tmp_char;
//--- check
if(index<0 || index+shift<0 || index+shift>=m_data_total)
return(false);
if(shift==0)
return(true);
//--- move
tmp_char=m_data[index];
if(shift>0)
{
if(MemMove(index,index+1,shift)<0)
return(false);
}
else
{
if(MemMove(index+shift+1,index+shift,-shift)<0)
return(false);
}
m_data[index+shift]=tmp_char;
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Deleting element from the specified position |
//+------------------------------------------------------------------+
bool CArrayChar::Delete(const int index)
{
//--- check
if(index<0 || index>=m_data_total)
return(false);
//--- delete
if(index<m_data_total-1 && MemMove(index,index+1,m_data_total-index-1)<0)
return(false);
m_data_total--;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Deleting range of elements |
//+------------------------------------------------------------------+
bool CArrayChar::DeleteRange(int from,int to)
{
//--- check
if(from<0 || to<0)
return(false);
if(from>to || from>=m_data_total)
return(false);
//--- delete
if(to>=m_data_total-1)
to=m_data_total-1;
if(MemMove(from,to+1,m_data_total-to-1)<0)
return(false);
m_data_total-=to-from+1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Equality comparison of two arrays |
//+------------------------------------------------------------------+
bool CArrayChar::CompareArray(const char &array[]) const
{
//--- compare
if(m_data_total!=ArraySize(array))
return(false);
for(int i=0;i<m_data_total;i++)
if(m_data[i]!=array[i])
return(false);
//--- equal
return(true);
}
//+------------------------------------------------------------------+
//| Equality comparison of two arrays |
//+------------------------------------------------------------------+
bool CArrayChar::CompareArray(const CArrayChar *array) const
{
//--- check
if(!CheckPointer(array))
return(false);
//--- compare
if(m_data_total!=array.m_data_total)
return(false);
for(int i=0;i<m_data_total;i++)
if(m_data[i]!=array.m_data[i])
return(false);
//--- equal
return(true);
}
//+------------------------------------------------------------------+
//| Method QuickSort |
//+------------------------------------------------------------------+
void CArrayChar::QuickSort(int beg,int end,const int mode)
{
int i,j;
char p_char;
char t_char;
//--- check
if(beg<0 || end<0)
return;
//--- sort
i=beg;
j=end;
while(i<end)
{
//--- ">>1" is quick division by 2
p_char=m_data[(beg+end)>>1];
while(i<j)
{
while(m_data[i]<p_char)
{
//--- control the output of the array bounds
if(i==m_data_total-1)
break;
i++;
}
while(m_data[j]>p_char)
{
//--- control the output of the array bounds
if(j==0)
break;
j--;
}
if(i<=j)
{
t_char=m_data[i];
m_data[i++]=m_data[j];
m_data[j]=t_char;
//--- control the output of the array bounds
if(j==0)
break;
j--;
}
}
if(beg<j)
QuickSort(beg,j);
beg=i;
j=end;
}
}
//+------------------------------------------------------------------+
//| Inserting element in a sorted array |
//+------------------------------------------------------------------+
bool CArrayChar::InsertSort(const char element)
{
int pos;
//--- check
if(!IsSorted())
return(false);
//--- check/reserve elements of array
if(!Reserve(1))
return(false);
//--- if the array is empty, add an element
if(m_data_total==0)
{
m_data[m_data_total++]=element;
return(true);
}
//--- find position and insert
pos=QuickSearch(element);
if(m_data[pos]>element)
Insert(element,pos);
else
Insert(element,pos+1);
//--- restore the sorting flag after Insert(...)
m_sort_mode=0;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Search of position of element in a array |
//+------------------------------------------------------------------+
int CArrayChar::SearchLinear(const char element) const
{
//--- check
if(m_data_total==0)
return(-1);
//---
for(int i=0;i<m_data_total;i++)
if(m_data[i]==element)
return(i);
//--- not found
return(-1);
}
//+------------------------------------------------------------------+
//| Quick search of position of element in a sorted array |
//+------------------------------------------------------------------+
int CArrayChar::QuickSearch(const char element) const
{
int i,j,m=-1;
char t_char;
//--- search
i=0;
j=m_data_total-1;
while(j>=i)
{
//--- ">>1" is quick division by 2
m=(j+i)>>1;
if(m<0 || m>=m_data_total)
break;
t_char=m_data[m];
if(t_char==element)
break;
if(t_char>element)
j=m-1;
else
i=m+1;
}
//--- position
return(m);
}
//+------------------------------------------------------------------+
//| Search of position of element in a sorted array |
//+------------------------------------------------------------------+
int CArrayChar::Search(const char element) const
{
int pos;
//--- check
if(m_data_total==0 || !IsSorted())
return(-1);
//--- search
pos=QuickSearch(element);
if(m_data[pos]==element)
return(pos);
//--- not found
return(-1);
}
//+------------------------------------------------------------------+
//| Search position of the first element which is greater than |
//| specified in a sorted array |
//+------------------------------------------------------------------+
int CArrayChar::SearchGreat(const char element) const
{
int pos;
//--- check
if(m_data_total==0 || !IsSorted())
return(-1);
//--- search
pos=QuickSearch(element);
while(m_data[pos]<=element)
if(++pos==m_data_total)
return(-1);
//--- position
return(pos);
}
//+------------------------------------------------------------------+
//| Search position of the first element which is less than |
//| specified in the sorted array |
//+------------------------------------------------------------------+
int CArrayChar::SearchLess(const char element) const
{
int pos;
//--- check
if(m_data_total==0 || !IsSorted())
return(-1);
//--- search
pos=QuickSearch(element);
while(m_data[pos]>=element)
if(pos--==0)
return(-1);
//--- position
return(pos);
}
//+------------------------------------------------------------------+
//| Search position of the first element which is greater than or |
//| equal to the specified in a sorted array |
//+------------------------------------------------------------------+
int CArrayChar::SearchGreatOrEqual(const char element) const
{
//--- check
if(m_data_total==0 || !IsSorted())
return(-1);
//--- search
for(int pos=QuickSearch(element);pos<m_data_total;pos++)
if(m_data[pos]>=element)
return(pos);
//--- not found
return(-1);
}
//+------------------------------------------------------------------+
//| Search position of the first element which is less than or equal |
//| to the specified in a sorted array |
//+------------------------------------------------------------------+
int CArrayChar::SearchLessOrEqual(const char element) const
{
//--- check
if(m_data_total==0 || !IsSorted())
return(-1);
//--- search
for(int pos=QuickSearch(element);pos>=0;pos--)
if(m_data[pos]<=element)
return(pos);
//--- not found
return(-1);
}
//+------------------------------------------------------------------+
//| Find position of first appearance of element in a sorted array |
//+------------------------------------------------------------------+
int CArrayChar::SearchFirst(const char element) const
{
int pos;
//--- check
if(m_data_total==0 || !IsSorted())
return(-1);
//--- search
pos=QuickSearch(element);
if(m_data[pos]==element)
{
while(m_data[pos]==element)
if(pos--==0)
break;
return(pos+1);
}
//--- not found
return(-1);
}
//+------------------------------------------------------------------+
//| Find position of last appearance of element in a sorted array |
//+------------------------------------------------------------------+
int CArrayChar::SearchLast(const char element) const
{
int pos;
//--- check
if(m_data_total==0 || !IsSorted())
return(-1);
//--- search
pos=QuickSearch(element);
if(m_data[pos]==element)
{
while(m_data[pos]==element)
if(++pos==m_data_total)
break;
return(pos-1);
}
//--- not found
return(-1);
}
//+------------------------------------------------------------------+
//| Writing array to file |
//+------------------------------------------------------------------+
bool CArrayChar::Save(const int file_handle)
{
int i=0;
//--- check
if(!CArray::Save(file_handle))
return(false);
//--- write array length
if(FileWriteInteger(file_handle,m_data_total,INT_VALUE)!=INT_VALUE)
return(false);
//--- write array
for(i=0;i<m_data_total;i++)
if(FileWriteInteger(file_handle,m_data[i],CHAR_VALUE)!=CHAR_VALUE)
break;
//--- result
return(i==m_data_total);
}
//+------------------------------------------------------------------+
//| Reading array from file |
//+------------------------------------------------------------------+
bool CArrayChar::Load(const int file_handle)
{
int i,num;
//--- check
if(!CArray::Load(file_handle))
return(false);
//--- read array length
num=FileReadInteger(file_handle,INT_VALUE);
//--- read array
Clear();
if(num!=0)
{
if(!Reserve(num))
return(false);
for(i=0;i<num;i++)
{
m_data[i]=(char)FileReadInteger(file_handle,CHAR_VALUE);
m_data_total++;
if(FileIsEnding(file_handle))
break;
}
}
m_sort_mode=-1;
//--- result
return(m_data_total==num);
}
//+------------------------------------------------------------------+
+777
View File
@@ -0,0 +1,777 @@
//+------------------------------------------------------------------+
//| ArrayDouble.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include "Array.mqh"
//+------------------------------------------------------------------+
//| Class CArrayDouble. |
//| Puprpose: Class of dynamic array variables of double type. |
//| Derives from class CArray. |
//+------------------------------------------------------------------+
class CArrayDouble : public CArray
{
protected:
double m_data[]; // data array
double m_delta; // search tolerance
public:
CArrayDouble(void);
~CArrayDouble(void);
//--- methods of access to protected data
void Delta(const double delta) { m_delta=MathAbs(delta); }
//--- method of identifying the object
virtual int Type(void) const { return(TYPE_DOUBLE); }
//--- methods for working with files
virtual bool Save(const int file_handle);
virtual bool Load(const int file_handle);
//--- methods of managing dynamic memory
bool Reserve(const int size);
bool Resize(const int size);
bool Shutdown(void);
//--- methods of filling the array
bool Add(const double element);
bool AddArray(const double &src[]);
bool AddArray(const CArrayDouble *src);
bool Insert(const double element,const int pos);
bool InsertArray(const double &src[],const int pos);
bool InsertArray(const CArrayDouble *src,const int pos);
bool AssignArray(const double &src[]);
bool AssignArray(const CArrayDouble *src);
//--- method of access to the array
double At(const int index) const;
double operator[](const int index) const { return(At(index)); }
//--- methods of searching for minimum and maximum
int Minimum(const int start,const int count) const { return(CArray::Minimum(m_data,start,count)); }
int Maximum(const int start,const int count) const { return(CArray::Maximum(m_data,start,count)); }
//--- methods of changing
bool Update(const int index,const double element);
bool Shift(const int index,const int shift);
//--- methods of deleting
bool Delete(const int index);
bool DeleteRange(int from,int to);
//--- methods for comparing arrays
bool CompareArray(const double &array[]) const;
bool CompareArray(const CArrayDouble *array) const;
//--- methods for working with a sorted array
bool InsertSort(const double element);
int Search(const double element) const;
int SearchGreat(const double element) const;
int SearchLess(const double element) const;
int SearchGreatOrEqual(const double element) const;
int SearchLessOrEqual(const double element) const;
int SearchFirst(const double element) const;
int SearchLast(const double element) const;
int SearchLinear(const double element) const;
protected:
virtual void QuickSort(int beg,int end,const int mode=0);
int QuickSearch(const double element) const;
int MemMove(const int dest,const int src,int count);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CArrayDouble::CArrayDouble(void) : m_delta(0.0)
{
m_data_max=ArraySize(m_data);
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CArrayDouble::~CArrayDouble(void)
{
if(m_data_max!=0)
Shutdown();
}
//+------------------------------------------------------------------+
//| Moving the memory within a single array |
//+------------------------------------------------------------------+
int CArrayDouble::MemMove(const int dest,const int src,int count)
{
int i;
//--- check parameters
if(dest<0 || src<0 || count<0)
return(-1);
//--- check count
if(src+count>m_data_total)
count=m_data_total-src;
if(count<0)
return(-1);
//--- no need to copy
if(dest==src || count==0)
return(dest);
//--- check data total
if(dest+count>m_data_total)
{
if(m_data_max<dest+count)
return(-1);
m_data_total=dest+count;
}
//--- copy
if(dest<src)
{
//--- copy from left to right
for(i=0;i<count;i++)
m_data[dest+i]=m_data[src+i];
}
else
{
//--- copy from right to left
for(i=count-1;i>=0;i--)
m_data[dest+i]=m_data[src+i];
}
//--- successful
return(dest);
}
//+------------------------------------------------------------------+
//| Request for more memory in an array. Checks if the requested |
//| number of free elements already exists; allocates additional |
//| memory with a given step |
//+------------------------------------------------------------------+
bool CArrayDouble::Reserve(const int size)
{
int new_size;
//--- check
if(size<=0)
return(false);
//--- resize array
if(Available()<size)
{
new_size=m_data_max+m_step_resize*(1+(size-Available())/m_step_resize);
if(new_size<0)
//--- overflow occurred when calculating new_size
return(false);
if((m_data_max=ArrayResize(m_data,new_size))==-1)
m_data_max=ArraySize(m_data);
}
//--- result
return(Available()>=size);
}
//+------------------------------------------------------------------+
//| Resizing (with removal of elements on the right) |
//+------------------------------------------------------------------+
bool CArrayDouble::Resize(const int size)
{
int new_size;
//--- check
if(size<0)
return(false);
//--- resize array
new_size=m_step_resize*(1+size/m_step_resize);
if(m_data_max!=new_size)
{
if((m_data_max=ArrayResize(m_data,new_size))==-1)
{
m_data_max=ArraySize(m_data);
return(false);
}
}
if(m_data_total>size)
m_data_total=size;
//--- result
return(m_data_max==new_size);
}
//+------------------------------------------------------------------+
//| Complete cleaning of the array with the release of memory |
//+------------------------------------------------------------------+
bool CArrayDouble::Shutdown(void)
{
//--- check
if(m_data_max==0)
return(true);
//--- clean
if(ArrayResize(m_data,0)==-1)
return(false);
m_data_total=0;
m_data_max=0;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Adding an element to the end of the array |
//+------------------------------------------------------------------+
bool CArrayDouble::Add(const double element)
{
//--- check/reserve elements of array
if(!Reserve(1))
return(false);
//--- add
m_data[m_data_total++]=element;
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Adding an element to the end of the array from another array |
//+------------------------------------------------------------------+
bool CArrayDouble::AddArray(const double &src[])
{
int num=ArraySize(src);
//--- check/reserve elements of array
if(!Reserve(num))
return(false);
//--- add
for(int i=0;i<num;i++)
m_data[m_data_total++]=src[i];
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Adding an element to the end of the array from another array |
//+------------------------------------------------------------------+
bool CArrayDouble::AddArray(const CArrayDouble *src)
{
int num;
//--- check
if(!CheckPointer(src))
return(false);
//--- check/reserve elements of array
num=src.Total();
if(!Reserve(num))
return(false);
//--- add
for(int i=0;i<num;i++)
m_data[m_data_total++]=src.m_data[i];
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Inserting an element in the specified position |
//+------------------------------------------------------------------+
bool CArrayDouble::Insert(const double element,const int pos)
{
//--- check/reserve elements of array
if(pos<0 || !Reserve(1))
return(false);
//--- insert
m_data_total++;
if(pos<m_data_total-1)
{
if(MemMove(pos+1,pos,m_data_total-pos-1)<0)
return(false);
m_data[pos]=element;
}
else
m_data[m_data_total-1]=element;
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Inserting elements in the specified position |
//+------------------------------------------------------------------+
bool CArrayDouble::InsertArray(const double &src[],const int pos)
{
int num=ArraySize(src);
//--- check/reserve elements of array
if(!Reserve(num))
return(false);
//--- insert
if(MemMove(num+pos,pos,m_data_total-pos)<0)
return(false);
for(int i=0;i<num;i++)
m_data[i+pos]=src[i];
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Inserting elements in the specified position |
//+------------------------------------------------------------------+
bool CArrayDouble::InsertArray(const CArrayDouble *src,const int pos)
{
int num;
//--- check
if(!CheckPointer(src))
return(false);
//--- check/reserve elements of array
num=src.Total();
if(!Reserve(num))
return(false);
//--- insert
if(MemMove(num+pos,pos,m_data_total-pos)<0)
return(false);
for(int i=0;i<num;i++)
m_data[i+pos]=src.m_data[i];
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Assignment (copying) of another array |
//+------------------------------------------------------------------+
bool CArrayDouble::AssignArray(const double &src[])
{
int num=ArraySize(src);
//--- check/reserve elements of array
Clear();
if(m_data_max<num)
{
if(!Reserve(num))
return(false);
}
else
Resize(num);
//--- copy array
for(int i=0;i<num;i++)
{
m_data[i]=src[i];
m_data_total++;
}
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Assignment (copying) of another array |
//+------------------------------------------------------------------+
bool CArrayDouble::AssignArray(const CArrayDouble *src)
{
int num;
//--- check
if(!CheckPointer(src))
return(false);
//--- check/reserve elements of array
num=src.m_data_total;
Clear();
if(m_data_max<num)
{
if(!Reserve(num))
return(false);
}
else
Resize(num);
//--- copy array
for(int i=0;i<num;i++)
{
m_data[i]=src.m_data[i];
m_data_total++;
}
m_sort_mode=src.SortMode();
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Access to data in the specified position |
//+------------------------------------------------------------------+
double CArrayDouble::At(const int index) const
{
//--- check
if(index<0 || index>=m_data_total)
return(DBL_MAX);
//--- result
return(m_data[index]);
}
//+------------------------------------------------------------------+
//| Updating element in the specified position |
//+------------------------------------------------------------------+
bool CArrayDouble::Update(const int index,const double element)
{
//--- check
if(index<0 || index>=m_data_total)
return(false);
//--- update
m_data[index]=element;
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Moving element from the specified position |
//| on the specified shift |
//+------------------------------------------------------------------+
bool CArrayDouble::Shift(const int index,const int shift)
{
double tmp_double;
//--- check
if(index<0 || index+shift<0 || index+shift>=m_data_total)
return(false);
if(shift==0)
return(true);
//--- move
tmp_double=m_data[index];
if(shift>0)
{
if(MemMove(index,index+1,shift)<0)
return(false);
}
else
{
if(MemMove(index+shift+1,index+shift,-shift)<0)
return(false);
}
m_data[index+shift]=tmp_double;
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Deleting element from the specified position |
//+------------------------------------------------------------------+
bool CArrayDouble::Delete(const int index)
{
//--- check
if(index<0 || index>=m_data_total)
return(false);
//--- delete
if(index<m_data_total-1 && MemMove(index,index+1,m_data_total-index-1)<0)
return(false);
m_data_total--;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Deleting range of elements |
//+------------------------------------------------------------------+
bool CArrayDouble::DeleteRange(int from,int to)
{
//--- check
if(from<0 || to<0)
return(false);
if(from>to || from>=m_data_total)
return(false);
//--- delete
if(to>=m_data_total-1)
to=m_data_total-1;
if(MemMove(from,to+1,m_data_total-to-1)<0)
return(false);
m_data_total-=to-from+1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Equality comparison of two arrays |
//+------------------------------------------------------------------+
bool CArrayDouble::CompareArray(const double &array[]) const
{
//--- compare
if(m_data_total!=ArraySize(array))
return(false);
for(int i=0;i<m_data_total;i++)
if(m_data[i]!=array[i])
return(false);
//--- equal
return(true);
}
//+------------------------------------------------------------------+
//| Equality comparison of two arrays |
//+------------------------------------------------------------------+
bool CArrayDouble::CompareArray(const CArrayDouble *array) const
{
//--- check
if(!CheckPointer(array))
return(false);
//--- compare
if(m_data_total!=array.m_data_total)
return(false);
for(int i=0;i<m_data_total;i++)
if(m_data[i]!=array.m_data[i])
return(false);
//--- equal
return(true);
}
//+------------------------------------------------------------------+
//| Method QuickSort |
//+------------------------------------------------------------------+
void CArrayDouble::QuickSort(int beg,int end,const int mode)
{
int i,j;
double p_double,t_double;
//--- check
if(beg<0 || end<0)
return;
//--- sort
i=beg;
j=end;
while(i<end)
{
//--- ">>1" is quick division by 2
p_double=m_data[(beg+end)>>1];
while(i<j)
{
while(m_data[i]<p_double)
{
//--- control the output of the array bounds
if(i==m_data_total-1)
break;
i++;
}
while(m_data[j]>p_double)
{
//--- control the output of the array bounds
if(j==0)
break;
j--;
}
if(i<=j)
{
t_double=m_data[i];
m_data[i++]=m_data[j];
m_data[j]=t_double;
//--- control the output of the array bounds
if(j==0)
break;
j--;
}
}
if(beg<j)
QuickSort(beg,j);
beg=i;
j=end;
}
}
//+------------------------------------------------------------------+
//| Inserting element in a sorted array |
//+------------------------------------------------------------------+
bool CArrayDouble::InsertSort(const double element)
{
int pos;
//--- check
if(!IsSorted())
return(false);
//--- check/reserve elements of array
if(!Reserve(1))
return(false);
//--- if the array is empty, add an element
if(m_data_total==0)
{
m_data[m_data_total++]=element;
return(true);
}
//--- search position and insert
pos=QuickSearch(element);
if(m_data[pos]>element)
Insert(element,pos);
else
Insert(element,pos+1);
//--- restore the sorting flag after Insert(...)
m_sort_mode=0;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Search of position of element in a array |
//+------------------------------------------------------------------+
int CArrayDouble::SearchLinear(const double element) const
{
//--- check
if(m_data_total==0)
return(-1);
//---
for(int i=0;i<m_data_total;i++)
if(MathAbs(m_data[i]-element)<=m_delta)
return(i);
//--- not found
return(-1);
}
//+------------------------------------------------------------------+
//| Quick search of position of element in a sorted array |
//+------------------------------------------------------------------+
int CArrayDouble::QuickSearch(const double element) const
{
int i,j,m=-1;
double t_double;
//--- search
i=0;
j=m_data_total-1;
while(j>=i)
{
//--- ">>1" is quick division by 2
m=(j+i)>>1;
if(m<0 || m>=m_data_total)
break;
t_double=m_data[m];
//--- compare with delta
if(MathAbs(t_double-element)<=m_delta)
break;
if(t_double>element)
j=m-1;
else
i=m+1;
}
//--- position
return(m);
}
//+------------------------------------------------------------------+
//| Search of position of element in a sorted array |
//+------------------------------------------------------------------+
int CArrayDouble::Search(const double element) const
{
int pos;
//--- check
if(m_data_total==0 || !IsSorted())
return(-1);
//--- search
pos=QuickSearch(element);
//--- compare with delta
if(MathAbs(m_data[pos]-element)<=m_delta)
return(pos);
//--- not found
return(-1);
}
//+------------------------------------------------------------------+
//| Search position of the first element which is greater than |
//| specified in a sorted array |
//+------------------------------------------------------------------+
int CArrayDouble::SearchGreat(const double element) const
{
int pos;
//--- check
if(m_data_total==0 || !IsSorted())
return(-1);
//--- search
pos=QuickSearch(element);
//--- compare with delta
while(m_data[pos]<=element+m_delta)
if(++pos==m_data_total)
return(-1);
//--- position
return(pos);
}
//+------------------------------------------------------------------+
//| Search position of the first element which is less than |
//| specified in the sorted array |
//+------------------------------------------------------------------+
int CArrayDouble::SearchLess(const double element) const
{
int pos;
//--- check
if(m_data_total==0 || !IsSorted())
return(-1);
//--- search
pos=QuickSearch(element);
//--- compare with delta
while(m_data[pos]>=element-m_delta)
if(pos--==0)
return(-1);
//--- position
return(pos);
}
//+------------------------------------------------------------------+
//| Search position of the first element which is greater than or |
//| equal to the specified in a sorted array |
//+------------------------------------------------------------------+
int CArrayDouble::SearchGreatOrEqual(const double element) const
{
//--- check
if(m_data_total==0 || !IsSorted())
return(-1);
//--- search
for(int pos=QuickSearch(element);pos<m_data_total;pos++)
if(m_data[pos]>=element)
return(pos);
//--- not found
return(-1);
}
//+------------------------------------------------------------------+
//| Search position of the first element which is less than or equal |
//| to the specified in a sorted array |
//+------------------------------------------------------------------+
int CArrayDouble::SearchLessOrEqual(const double element) const
{
//--- check
if(m_data_total==0 || !IsSorted())
return(-1);
//--- search
for(int pos=QuickSearch(element);pos>=0;pos--)
if(m_data[pos]<=element)
return(pos);
//--- not found
return(-1);
}
//+------------------------------------------------------------------+
//| Find position of first appearance of element in a sorted array |
//+------------------------------------------------------------------+
int CArrayDouble::SearchFirst(const double element) const
{
int pos;
//--- check
if(m_data_total==0 || !IsSorted())
return(-1);
//--- search
pos=QuickSearch(element);
if(m_data[pos]==element)
{
//--- compare with delta
while(MathAbs(m_data[pos]-element)<=m_delta)
if(pos--==0)
break;
return(pos+1);
}
//--- not found
return(-1);
}
//+------------------------------------------------------------------+
//| Find position of last appearance of element in a sorted array |
//+------------------------------------------------------------------+
int CArrayDouble::SearchLast(const double element) const
{
int pos;
//--- check
if(m_data_total==0 || !IsSorted())
return(-1);
//--- search
pos=QuickSearch(element);
if(m_data[pos]==element)
{
//--- compare with delta
while(MathAbs(m_data[pos]-element)<=m_delta)
if(++pos==m_data_total)
break;
return(pos-1);
}
//--- not found
return(-1);
}
//+------------------------------------------------------------------+
//| Writing array to file |
//+------------------------------------------------------------------+
bool CArrayDouble::Save(const int file_handle)
{
int i=0;
//--- check
if(!CArray::Save(file_handle))
return(false);
//--- write array length
if(FileWriteInteger(file_handle,m_data_total,INT_VALUE)!=INT_VALUE)
return(false);
//--- write array
for(i=0;i<m_data_total;i++)
if(FileWriteDouble(file_handle,m_data[i])!=sizeof(double))
break;
//--- result
return(i==m_data_total);
}
//+------------------------------------------------------------------+
//| Reading array from file |
//+------------------------------------------------------------------+
bool CArrayDouble::Load(const int file_handle)
{
int i=0,num;
//--- check
if(!CArray::Load(file_handle))
return(false);
//--- read array length
num=FileReadInteger(file_handle,INT_VALUE);
//--- read array
Clear();
if(num!=0)
{
if(!Reserve(num))
return(false);
for(i=0;i<num;i++)
{
m_data[i]=FileReadDouble(file_handle);
m_data_total++;
if(FileIsEnding(file_handle))
break;
}
}
m_sort_mode=-1;
//--- result
return(m_data_total==num);
}
//+------------------------------------------------------------------+
+778
View File
@@ -0,0 +1,778 @@
//+------------------------------------------------------------------+
//| ArrayFloat.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include "Array.mqh"
//+------------------------------------------------------------------+
//| Class CArrayFloat. |
//| Purpose: Class of dynamic array of variable |
//| of float type. |
//| Derives from class CArray. |
//+------------------------------------------------------------------+
class CArrayFloat : public CArray
{
protected:
float m_data[]; // data array
float m_delta; // search tolerance
public:
CArrayFloat(void);
~CArrayFloat(void);
//--- methods of access to protected data
void Delta(const float delta) { m_delta=(float)MathAbs(delta); }
//--- method of identifying the object
virtual int Type(void) const { return(TYPE_FLOAT); }
//--- methods for working with files
virtual bool Save(const int file_handle);
virtual bool Load(const int file_handle);
//--- methods of managing dynamic memory
bool Reserve(const int size);
bool Resize(const int size);
bool Shutdown(void);
//--- methods of filling the array
bool Add(const float element);
bool AddArray(const float &src[]);
bool AddArray(const CArrayFloat *src);
bool Insert(const float element,const int pos);
bool InsertArray(const float &src[],const int pos);
bool InsertArray(const CArrayFloat *src,const int pos);
bool AssignArray(const float &src[]);
bool AssignArray(const CArrayFloat *src);
//--- method of access to the array
float At(const int index) const;
float operator[](const int index) const { return(At(index)); }
//--- methods of searching for minimum and maximum
int Minimum(const int start,const int count) const { return(CArray::Minimum(m_data,start,count)); }
int Maximum(const int start,const int count) const { return(CArray::Maximum(m_data,start,count)); }
//--- methods of changing
bool Update(const int index,const float element);
bool Shift(const int index,const int shift);
//--- methods deleting
bool Delete(const int index);
bool DeleteRange(int from,int to);
//--- methods for comparing arrays
bool CompareArray(const float &array[]) const;
bool CompareArray(const CArrayFloat *array) const;
//--- methods for working with the sorted array
bool InsertSort(const float element);
int Search(const float element) const;
int SearchGreat(const float element) const;
int SearchLess(const float element) const;
int SearchGreatOrEqual(const float element) const;
int SearchLessOrEqual(const float element) const;
int SearchFirst(const float element) const;
int SearchLast(const float element) const;
int SearchLinear(const float element) const;
protected:
virtual void QuickSort(int beg,int end,const int mode=0);
int QuickSearch(const float element) const;
int MemMove(const int dest,const int src,int count);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CArrayFloat::CArrayFloat(void) : m_delta(0.0)
{
//--- initialize protected data
m_data_max=ArraySize(m_data);
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CArrayFloat::~CArrayFloat(void)
{
if(m_data_max!=0)
Shutdown();
}
//+------------------------------------------------------------------+
//| Moving the memory within a single array |
//+------------------------------------------------------------------+
int CArrayFloat::MemMove(const int dest,const int src,int count)
{
int i;
//--- check parameters
if(dest<0 || src<0 || count<0)
return(-1);
//--- check count
if(src+count>m_data_total)
count=m_data_total-src;
if(count<0)
return(-1);
//--- no need to copy
if(dest==src || count==0)
return(dest);
//--- check data total
if(dest+count>m_data_total)
{
if(m_data_max<dest+count)
return(-1);
m_data_total=dest+count;
}
//--- copy
if(dest<src)
{
//--- copy from left to right
for(i=0;i<count;i++)
m_data[dest+i]=m_data[src+i];
}
else
{
//--- copy from right to left
for(i=count-1;i>=0;i--)
m_data[dest+i]=m_data[src+i];
}
//--- successful
return(dest);
}
//+------------------------------------------------------------------+
//| Request for more memory in an array. Checks if the requested |
//| number of free elements already exists; allocates additional |
//| memory with a given step |
//+------------------------------------------------------------------+
bool CArrayFloat::Reserve(const int size)
{
int new_size;
//--- check
if(size<=0)
return(false);
//--- resize array
if(Available()<size)
{
new_size=m_data_max+m_step_resize*(1+(size-Available())/m_step_resize);
if(new_size<0)
//--- overflow occurred when calculating new_size
return(false);
if((m_data_max=ArrayResize(m_data,new_size))==-1)
m_data_max=ArraySize(m_data);
}
//--- result
return(Available()>=size);
}
//+------------------------------------------------------------------+
//| Resizing (with removal of elements on the right) |
//+------------------------------------------------------------------+
bool CArrayFloat::Resize(const int size)
{
int new_size;
//--- check
if(size<0)
return(false);
//--- resize array
new_size=m_step_resize*(1+size/m_step_resize);
if(m_data_max!=new_size)
{
if((m_data_max=ArrayResize(m_data,new_size))==-1)
{
m_data_max=ArraySize(m_data);
return(false);
}
}
if(m_data_total>size)
m_data_total=size;
//--- result
return(m_data_max==new_size);
}
//+------------------------------------------------------------------+
//| Complete cleaning of the array with the release of memory |
//+------------------------------------------------------------------+
bool CArrayFloat::Shutdown(void)
{
//--- check
if(m_data_max==0)
return(true);
//--- clean
if(ArrayResize(m_data,0)==-1)
return(false);
m_data_total=0;
m_data_max=0;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Adding an element to the end of the array |
//+------------------------------------------------------------------+
bool CArrayFloat::Add(const float element)
{
//--- check/reserve elements of array
if(!Reserve(1))
return(false);
//--- add
m_data[m_data_total++]=element;
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Adding an element to the end of the array from another array |
//+------------------------------------------------------------------+
bool CArrayFloat::AddArray(const float &src[])
{
int num=ArraySize(src);
//--- check/reserve elements of array
if(!Reserve(num))
return(false);
//--- add
for(int i=0;i<num;i++)
m_data[m_data_total++]=src[i];
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Adding an element to the end of the array from another array |
//+------------------------------------------------------------------+
bool CArrayFloat::AddArray(const CArrayFloat *src)
{
int num;
//--- check
if(!CheckPointer(src))
return(false);
//--- check/reserve elements of array
num=src.Total();
if(!Reserve(num))
return(false);
//--- add
for(int i=0;i<num;i++)
m_data[m_data_total++]=src.m_data[i];
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Inserting an element in the specified position |
//+------------------------------------------------------------------+
bool CArrayFloat::Insert(const float element,const int pos)
{
//--- check/reserve elements of array
if(pos<0 || !Reserve(1))
return(false);
//--- insert
m_data_total++;
if(pos<m_data_total-1)
{
if(MemMove(pos+1,pos,m_data_total-pos-1)<0)
return(false);
m_data[pos]=element;
}
else
m_data[m_data_total-1]=element;
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Inserting elements in the specified position |
//+------------------------------------------------------------------+
bool CArrayFloat::InsertArray(const float &src[],const int pos)
{
int num=ArraySize(src);
//--- check/reserve elements of array
if(!Reserve(num))
return(false);
//--- insert
if(MemMove(num+pos,pos,m_data_total-pos)<0)
return(false);
for(int i=0;i<num;i++)
m_data[i+pos]=src[i];
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Inserting elements in the specified position |
//+------------------------------------------------------------------+
bool CArrayFloat::InsertArray(const CArrayFloat *src,const int pos)
{
int num;
//--- check
if(!CheckPointer(src))
return(false);
//--- check/reserve elements of array
num=src.Total();
if(!Reserve(num))
return(false);
//--- insert
if(MemMove(num+pos,pos,m_data_total-pos)<0)
return(false);
for(int i=0;i<num;i++)
m_data[i+pos]=src.m_data[i];
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Assignment (copying) of another array |
//+------------------------------------------------------------------+
bool CArrayFloat::AssignArray(const float &src[])
{
int num=ArraySize(src);
//--- check/reserve elements of array
Clear();
if(m_data_max<num)
{
if(!Reserve(num))
return(false);
}
else
Resize(num);
//--- copy array
for(int i=0;i<num;i++)
{
m_data[i]=src[i];
m_data_total++;
}
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Assignment (copying) of another array |
//+------------------------------------------------------------------+
bool CArrayFloat::AssignArray(const CArrayFloat *src)
{
int num;
//--- check
if(!CheckPointer(src))
return(false);
//--- check/reserve elements of array
num=src.m_data_total;
Clear();
if(m_data_max<num)
{
if(!Reserve(num))
return(false);
}
else
Resize(num);
//--- copy array
for(int i=0;i<num;i++)
{
m_data[i]=src.m_data[i];
m_data_total++;
}
m_sort_mode=src.SortMode();
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Access to data in the specified position |
//+------------------------------------------------------------------+
float CArrayFloat::At(const int index) const
{
//--- check
if(index<0 || index>=m_data_total)
return(FLT_MAX);
//--- result
return(m_data[index]);
}
//+------------------------------------------------------------------+
//| Updating element in the specified position |
//+------------------------------------------------------------------+
bool CArrayFloat::Update(const int index,const float element)
{
//--- check
if(index<0 || index>=m_data_total)
return(false);
//--- update
m_data[index]=element;
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Moving element from the specified position |
//| on the specified shift |
//+------------------------------------------------------------------+
bool CArrayFloat::Shift(const int index,const int shift)
{
float tmp_float;
//--- check
if(index<0 || index+shift<0 || index+shift>=m_data_total)
return(false);
if(shift==0)
return(true);
//--- move
tmp_float=m_data[index];
if(shift>0)
{
if(MemMove(index,index+1,shift)<0)
return(false);
}
else
{
if(MemMove(index+shift+1,index+shift,-shift)<0)
return(false);
}
m_data[index+shift]=tmp_float;
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Deleting element from the specified position |
//+------------------------------------------------------------------+
bool CArrayFloat::Delete(const int index)
{
//--- check
if(index<0 || index>=m_data_total)
return(false);
//--- delete
if(index<m_data_total-1 && MemMove(index,index+1,m_data_total-index-1)<0)
return(false);
m_data_total--;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Deleting range of elements |
//+------------------------------------------------------------------+
bool CArrayFloat::DeleteRange(int from,int to)
{
//--- check
if(from<0 || to<0)
return(false);
if(from>to || from>=m_data_total)
return(false);
//--- delete
if(to>=m_data_total-1)
to=m_data_total-1;
if(MemMove(from,to+1,m_data_total-to-1)<0)
return(false);
m_data_total-=to-from+1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Equality comparison of two arrays |
//+------------------------------------------------------------------+
bool CArrayFloat::CompareArray(const float &array[]) const
{
//--- compare
if(m_data_total!=ArraySize(array))
return(false);
for(int i=0;i<m_data_total;i++)
if(m_data[i]!=array[i])
return(false);
//--- equal
return(true);
}
//+------------------------------------------------------------------+
//| Equality comparison of two arrays |
//+------------------------------------------------------------------+
bool CArrayFloat::CompareArray(const CArrayFloat *array) const
{
//--- check
if(!CheckPointer(array)) return(false);
//--- compare
if(m_data_total!=array.m_data_total)
return(false);
for(int i=0;i<m_data_total;i++)
if(m_data[i]!=array.m_data[i])
return(false);
//--- equal
return(true);
}
//+------------------------------------------------------------------+
//| Method QuickSort |
//+------------------------------------------------------------------+
void CArrayFloat::QuickSort(int beg,int end,const int mode)
{
int i,j;
float p_float,t_float;
//--- check
if(beg<0 || end<0)
return;
//--- sort
i=beg;
j=end;
while(i<end)
{
//--- ">>1" is quick division by 2
p_float=m_data[(beg+end)>>1];
while(i<j)
{
while(m_data[i]<p_float)
{
//--- control the output of the array bounds
if(i==m_data_total-1)
break;
i++;
}
while(m_data[j]>p_float)
{
//--- control the output of the array bounds
if(j==0)
break;
j--;
}
if(i<=j)
{
t_float=m_data[i];
m_data[i++]=m_data[j];
m_data[j]=t_float;
//--- control the output of the array bounds
if(j==0)
break;
j--;
}
}
if(beg<j)
QuickSort(beg,j);
beg=i;
j=end;
}
}
//+------------------------------------------------------------------+
//| Inserting element in a sorted array |
//+------------------------------------------------------------------+
bool CArrayFloat::InsertSort(const float element)
{
int pos;
//--- check
if(!IsSorted())
return(false);
//--- check/reserve elements of array
if(!Reserve(1))
return(false);
//--- if the array is empty, add an element
if(m_data_total==0)
{
m_data[m_data_total++]=element;
return(true);
}
//--- search position and insert
pos=QuickSearch(element);
if(m_data[pos]>element)
Insert(element,pos);
else
Insert(element,pos+1);
//--- restore the sorting flag after Insert(...)
m_sort_mode=0;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Search of position of element in a array |
//+------------------------------------------------------------------+
int CArrayFloat::SearchLinear(const float element) const
{
//--- check
if(m_data_total==0)
return(-1);
//---
for(int i=0;i<m_data_total;i++)
if(MathAbs(m_data[i]-element)<=m_delta)
return(i);
//--- not found
return(-1);
}
//+------------------------------------------------------------------+
//| Quick search of position of element in a sorted array |
//+------------------------------------------------------------------+
int CArrayFloat::QuickSearch(const float element) const
{
int i,j,m=-1;
float t_float;
//--- search
i=0;
j=m_data_total-1;
while(j>=i)
{
//--- ">>1" is quick division by 2
m=(j+i)>>1;
if(m<0 || m>=m_data_total)
break;
t_float=m_data[m];
//--- compare with delta
if(MathAbs(t_float-element)<=m_delta)
break;
if(t_float>element)
j=m-1;
else
i=m+1;
}
//--- position
return(m);
}
//+------------------------------------------------------------------+
//| Search of position of element in a sorted array |
//+------------------------------------------------------------------+
int CArrayFloat::Search(const float element) const
{
int pos;
//--- check
if(m_data_total==0 || !IsSorted())
return(-1);
//--- search
pos=QuickSearch(element);
//--- compare with delta
if(MathAbs(m_data[pos]-element)<=m_delta)
return(pos);
//--- not found
return(-1);
}
//+------------------------------------------------------------------+
//| Search position of the first element which is greater than |
//| specified in a sorted array |
//+------------------------------------------------------------------+
int CArrayFloat::SearchGreat(const float element) const
{
int pos;
//--- check
if(m_data_total==0 || !IsSorted())
return(-1);
//--- search
pos=QuickSearch(element);
//--- compare with delta
while(m_data[pos]<=element+m_delta)
if(++pos==m_data_total)
return(-1);
//--- position
return(pos);
}
//+------------------------------------------------------------------+
//| Search position of the first element which is less than |
//| specified in the sorted array |
//+------------------------------------------------------------------+
int CArrayFloat::SearchLess(const float element) const
{
int pos;
//--- check
if(m_data_total==0 || !IsSorted())
return(-1);
//--- search
pos=QuickSearch(element);
//--- compare with delta
while(m_data[pos]>=element-m_delta)
if(pos--==0)
return(-1);
//--- position
return(pos);
}
//+------------------------------------------------------------------+
//| Search position of the first element which is greater than or |
//| equal to the specified in a sorted array |
//+------------------------------------------------------------------+
int CArrayFloat::SearchGreatOrEqual(const float element) const
{
//--- check
if(m_data_total==0 || !IsSorted())
return(-1);
//--- search
for(int pos=QuickSearch(element);pos<m_data_total;pos++)
if(m_data[pos]>=element)
return(pos);
//--- not found
return(-1);
}
//+------------------------------------------------------------------+
//| Search position of the first element which is less than or equal |
//| to the specified in a sorted array |
//+------------------------------------------------------------------+
int CArrayFloat::SearchLessOrEqual(const float element) const
{
//--- check
if(m_data_total==0 || !IsSorted())
return(-1);
//--- search
for(int pos=QuickSearch(element);pos>=0;pos--)
if(m_data[pos]<=element)
return(pos);
//--- not found
return(-1);
}
//+------------------------------------------------------------------+
//| Find position of first appearance of element in a sorted array |
//+------------------------------------------------------------------+
int CArrayFloat::SearchFirst(const float element) const
{
int pos;
//--- check
if(m_data_total==0 || !IsSorted())
return(-1);
//--- search
pos=QuickSearch(element);
if(m_data[pos]==element)
{
//--- compare with delta
while(MathAbs(m_data[pos]-element)<=m_delta)
if(pos--==0)
break;
return(pos+1);
}
//--- not found
return(-1);
}
//+------------------------------------------------------------------+
//| Find position of last appearance of element in a sorted array |
//+------------------------------------------------------------------+
int CArrayFloat::SearchLast(const float element) const
{
int pos;
//--- check
if(m_data_total==0 || !IsSorted())
return(-1);
//--- search
pos=QuickSearch(element);
if(m_data[pos]==element)
{
//--- compare with delta
while(MathAbs(m_data[pos]-element)<=m_delta)
if(++pos==m_data_total)
break;
return(pos-1);
}
//--- not found
return(-1);
}
//+------------------------------------------------------------------+
//| Writing array to file |
//+------------------------------------------------------------------+
bool CArrayFloat::Save(const int file_handle)
{
int i=0;
//--- check
if(!CArray::Save(file_handle))
return(false);
//--- write array length
if(FileWriteInteger(file_handle,m_data_total,INT_VALUE)!=INT_VALUE)
return(false);
//--- write array
for(i=0;i<m_data_total;i++)
if(FileWriteFloat(file_handle,m_data[i])!=sizeof(float))
break;
//--- result
return(i==m_data_total);
}
//+------------------------------------------------------------------+
//| Reading array from file |
//+------------------------------------------------------------------+
bool CArrayFloat::Load(const int file_handle)
{
int i=0,num;
//--- check
if(!CArray::Load(file_handle))
return(false);
//--- read array length
num=FileReadInteger(file_handle,INT_VALUE);
//--- read array
Clear();
if(num!=0)
{
if(!Reserve(num))
return(false);
for(i=0;i<num;i++)
{
m_data[i]=FileReadFloat(file_handle);
m_data_total++;
if(FileIsEnding(file_handle))
break;
}
}
m_sort_mode=-1;
//--- result
return(m_data_total==num);
}
//+------------------------------------------------------------------+
+770
View File
@@ -0,0 +1,770 @@
//+------------------------------------------------------------------+
//| ArrayInt.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include "Array.mqh"
//+------------------------------------------------------------------+
//| Class CArrayInt. |
//| Puprose: Class of dynamic array of variables |
//| of int or uint type. |
//| Derives from class CArray. |
//+------------------------------------------------------------------+
class CArrayInt : public CArray
{
protected:
int m_data[]; // data array
public:
CArrayInt(void);
~CArrayInt(void);
//--- method of identifying the object
virtual int Type(void) const { return(TYPE_INT); }
//--- methods for working with files
virtual bool Save(const int file_handle);
virtual bool Load(const int file_handle);
//--- methods of managing dynamic memory
bool Reserve(const int size);
bool Resize(const int size);
bool Shutdown(void);
//--- methods of filling the array
bool Add(const int element);
bool AddArray(const int &src[]);
bool AddArray(const CArrayInt *src);
bool Insert(const int element,const int pos);
bool InsertArray(const int &src[],const int pos);
bool InsertArray(const CArrayInt *src,const int pos);
bool AssignArray(const int &src[]);
bool AssignArray(const CArrayInt *src);
//--- method of access to the array
int At(const int index) const;
int operator[](const int index) const { return(At(index)); }
//--- methods of searching for minimum and maximum
int Minimum(const int start,const int count) const { return(CArray::Minimum(m_data,start,count)); }
int Maximum(const int start,const int count) const { return(CArray::Maximum(m_data,start,count)); }
//--- methods of changing
bool Update(const int index,const int element);
bool Shift(const int index,const int shift);
//--- methods of deleting
bool Delete(const int index);
bool DeleteRange(int from,int to);
//--- methods for comparing arrays
bool CompareArray(const int &array[]) const;
bool CompareArray(const CArrayInt *array) const;
//--- methods for working with the sorted array
bool InsertSort(const int element);
int Search(const int element) const;
int SearchGreat(const int element) const;
int SearchLess(const int element) const;
int SearchGreatOrEqual(const int element) const;
int SearchLessOrEqual(const int element) const;
int SearchFirst(const int element) const;
int SearchLast(const int element) const;
int SearchLinear(const int element) const;
protected:
virtual void QuickSort(int beg,int end,const int mode=0);
int QuickSearch(const int element) const;
int MemMove(const int dest,const int src,int count);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CArrayInt::CArrayInt(void)
{
//--- initialize protected data
m_data_max=ArraySize(m_data);
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CArrayInt::~CArrayInt(void)
{
if(m_data_max!=0)
Shutdown();
}
//+------------------------------------------------------------------+
//| Moving the memory within a single array |
//+------------------------------------------------------------------+
int CArrayInt::MemMove(const int dest,const int src,int count)
{
int i;
//--- check parameters
if(dest<0 || src<0 || count<0)
return(-1);
//--- check count
if(src+count>m_data_total)
count=m_data_total-src;
if(count<0)
return(-1);
//--- no need to copy
if(dest==src || count==0)
return(dest);
//--- check data total
if(dest+count>m_data_total)
{
if(m_data_max<dest+count)
return(-1);
m_data_total=dest+count;
}
//--- copy
if(dest<src)
{
//--- copy from left to right
for(i=0;i<count;i++)
m_data[dest+i]=m_data[src+i];
}
else
{
//--- copy from right to left
for(i=count-1;i>=0;i--)
m_data[dest+i]=m_data[src+i];
}
//--- successful
return(dest);
}
//+------------------------------------------------------------------+
//| Request for more memory in an array. Checks if the requested |
//| number of free elements already exists; allocates additional |
//| memory with a given step |
//+------------------------------------------------------------------+
bool CArrayInt::Reserve(const int size)
{
int new_size;
//--- check
if(size<=0)
return(false);
//--- resize array
if(Available()<size)
{
new_size=m_data_max+m_step_resize*(1+(size-Available())/m_step_resize);
if(new_size<0)
//--- overflow occurred when calculating new_size
return(false);
if((m_data_max=ArrayResize(m_data,new_size))==-1)
m_data_max=ArraySize(m_data);
}
//--- result
return(Available()>=size);
}
//+------------------------------------------------------------------+
//| Resizing (with removal of elements on the right) |
//+------------------------------------------------------------------+
bool CArrayInt::Resize(const int size)
{
int new_size;
//--- check
if(size<0)
return(false);
//--- resize array
new_size=m_step_resize*(1+size/m_step_resize);
if(m_data_max!=new_size)
{
if((m_data_max=ArrayResize(m_data,new_size))==-1)
{
m_data_max=ArraySize(m_data);
return(false);
}
}
if(m_data_total>size)
m_data_total=size;
//--- result
return(m_data_max==new_size);
}
//+------------------------------------------------------------------+
//| Complete cleaning of the array with the release of memory |
//+------------------------------------------------------------------+
bool CArrayInt::Shutdown(void)
{
//--- check
if(m_data_max==0)
return(true);
//--- clean
if(ArrayResize(m_data,0)==-1)
return(false);
m_data_total=0;
m_data_max=0;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Adding an element to the end of the array |
//+------------------------------------------------------------------+
bool CArrayInt::Add(const int element)
{
//--- check/reserve elements of array
if(!Reserve(1))
return(false);
//--- add
m_data[m_data_total++]=element;
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Adding an element to the end of the array from another array |
//+------------------------------------------------------------------+
bool CArrayInt::AddArray(const int &src[])
{
int num=ArraySize(src);
//--- check/reserve elements of array
if(!Reserve(num))
return(false);
//--- add
for(int i=0;i<num;i++)
m_data[m_data_total++]=src[i];
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Adding an element to the end of the array from another array |
//+------------------------------------------------------------------+
bool CArrayInt::AddArray(const CArrayInt *src)
{
int num;
//--- check
if(!CheckPointer(src))
return(false);
//--- check/reserve elements of array
num=src.Total();
if(!Reserve(num))
return(false);
//--- add
for(int i=0;i<num;i++)
m_data[m_data_total++]=src.m_data[i];
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Inserting an element in the specified position |
//+------------------------------------------------------------------+
bool CArrayInt::Insert(const int element,const int pos)
{
//--- check/reserve elements of array
if(pos<0 || !Reserve(1))
return(false);
//--- insert
m_data_total++;
if(pos<m_data_total-1)
{
if(MemMove(pos+1,pos,m_data_total-pos-1)<0)
return(false);
m_data[pos]=element;
}
else
m_data[m_data_total-1]=element;
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Inserting elements in the specified position |
//+------------------------------------------------------------------+
bool CArrayInt::InsertArray(const int &src[],const int pos)
{
int num=ArraySize(src);
//--- check/reserve elements of array
if(!Reserve(num))
return(false);
//--- insert
if(MemMove(num+pos,pos,m_data_total-pos)<0)
return(false);
for(int i=0;i<num;i++)
m_data[i+pos]=src[i];
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Inserting elements in the specified position |
//+------------------------------------------------------------------+
bool CArrayInt::InsertArray(const CArrayInt *src,const int pos)
{
int num;
//--- check
if(!CheckPointer(src))
return(false);
//--- check/reserve elements of array
num=src.Total();
if(!Reserve(num))
return(false);
//--- insert
if(MemMove(num+pos,pos,m_data_total-pos)<0)
return(false);
for(int i=0;i<num;i++)
m_data[i+pos]=src.m_data[i];
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Assignment (copying) of another array |
//+------------------------------------------------------------------+
bool CArrayInt::AssignArray(const int &src[])
{
int num=ArraySize(src);
//--- check/reserve elements of array
Clear();
if(m_data_max<num)
{
if(!Reserve(num))
return(false);
}
else
Resize(num);
//--- copy array
for(int i=0;i<num;i++)
{
m_data[i]=src[i];
m_data_total++;
}
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Assignment (copying) of another array |
//+------------------------------------------------------------------+
bool CArrayInt::AssignArray(const CArrayInt *src)
{
int num;
//--- check
if(!CheckPointer(src))
return(false);
//--- check/reserve elements of array
num=src.m_data_total;
Clear();
if(m_data_max<num)
{
if(!Reserve(num))
return(false);
}
else
Resize(num);
//--- copy array
for(int i=0;i<num;i++)
{
m_data[i]=src.m_data[i];
m_data_total++;
}
m_sort_mode=src.SortMode();
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Access to data in the specified position |
//+------------------------------------------------------------------+
int CArrayInt::At(const int index) const
{
//--- check
if(index<0 || index>=m_data_total)
return(INT_MAX);
//--- result
return(m_data[index]);
}
//+------------------------------------------------------------------+
//| Updating element in the specified position |
//+------------------------------------------------------------------+
bool CArrayInt::Update(const int index,const int element)
{
//--- check
if(index<0 || index>=m_data_total)
return(false);
//--- update
m_data[index]=element;
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Moving element from the specified position |
//| on the specified shift |
//+------------------------------------------------------------------+
bool CArrayInt::Shift(const int index,const int shift)
{
int tmp_int;
//--- check
if(index<0 || index+shift<0 || index+shift>=m_data_total)
return(false);
if(shift==0)
return(true);
//--- move
tmp_int=m_data[index];
if(shift>0)
{
if(MemMove(index,index+1,shift)<0)
return(false);
}
else
{
if(MemMove(index+shift+1,index+shift,-shift)<0)
return(false);
}
m_data[index+shift]=tmp_int;
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Deleting element from the specified position |
//+------------------------------------------------------------------+
bool CArrayInt::Delete(const int index)
{
//--- check
if(index<0 || index>=m_data_total)
return(false);
//--- delete
if(index<m_data_total-1 && MemMove(index,index+1,m_data_total-index-1)<0)
return(false);
m_data_total--;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Deleting range of elements |
//+------------------------------------------------------------------+
bool CArrayInt::DeleteRange(int from,int to)
{
//--- check
if(from<0 || to<0)
return(false);
if(from>to || from>=m_data_total)
return(false);
//--- delete
if(to>=m_data_total-1)
to=m_data_total-1;
if(MemMove(from,to+1,m_data_total-to-1)<0)
return(false);
m_data_total-=to-from+1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Equality comparison of two arrays |
//+------------------------------------------------------------------+
bool CArrayInt::CompareArray(const int &array[]) const
{
//--- compare
if(m_data_total!=ArraySize(array))
return(false);
for(int i=0;i<m_data_total;i++)
if(m_data[i]!=array[i])
return(false);
//--- equal
return(true);
}
//+------------------------------------------------------------------+
//| Equality comparison of two arrays |
//+------------------------------------------------------------------+
bool CArrayInt::CompareArray(const CArrayInt *array) const
{
//--- check
if(!CheckPointer(array))
return(false);
//--- compare
if(m_data_total!=array.m_data_total)
return(false);
for(int i=0;i<m_data_total;i++)
if(m_data[i]!=array.m_data[i])
return(false);
//--- equal
return(true);
}
//+------------------------------------------------------------------+
//| Method QuickSort |
//+------------------------------------------------------------------+
void CArrayInt::QuickSort(int beg,int end,const int mode)
{
int i,j;
int p_int,t_int;
//--- check
if(beg<0 || end<0)
return;
//--- sort
i=beg;
j=end;
while(i<end)
{
//--- ">>1" is quick division by 2
p_int=m_data[(beg+end)>>1];
while(i<j)
{
while(m_data[i]<p_int)
{
//--- control the output of the array bounds
if(i==m_data_total-1)
break;
i++;
}
while(m_data[j]>p_int)
{
//--- control the output of the array bounds
if(j==0)
break;
j--;
}
if(i<=j)
{
t_int=m_data[i];
m_data[i++]=m_data[j];
m_data[j]=t_int;
//--- control the output of the array bounds
if(j==0)
break;
j--;
}
}
if(beg<j)
QuickSort(beg,j);
beg=i;
j=end;
}
}
//+------------------------------------------------------------------+
//| Inserting element in a sorted array |
//+------------------------------------------------------------------+
bool CArrayInt::InsertSort(const int element)
{
int pos;
//--- check
if(!IsSorted())
return(false);
//--- check/reserve elements of array
if(!Reserve(1))
return(false);
//--- if the array is empty, add an element
if(m_data_total==0)
{
m_data[m_data_total++]=element;
return(true);
}
//--- find position and insert
pos=QuickSearch(element);
if(m_data[pos]>element)
Insert(element,pos);
else
Insert(element,pos+1);
//--- restore the sorting flag after Insert(...)
m_sort_mode=0;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Search of position of element in a array |
//+------------------------------------------------------------------+
int CArrayInt::SearchLinear(const int element) const
{
//--- check
if(m_data_total==0)
return(-1);
//---
for(int i=0;i<m_data_total;i++)
if(m_data[i]==element)
return(i);
//--- not found
return(-1);
}
//+------------------------------------------------------------------+
//| Quick search of position of element in a sorted array |
//+------------------------------------------------------------------+
int CArrayInt::QuickSearch(const int element) const
{
int i,j,m=-1;
int t_int;
//--- search
i=0;
j=m_data_total-1;
while(j>=i)
{
//--- ">>1" is quick division by 2
m=(j+i)>>1;
if(m<0 || m>=m_data_total)
break;
t_int=m_data[m];
if(t_int==element)
break;
if(t_int>element)
j=m-1;
else
i=m+1;
}
//--- position
return(m);
}
//+------------------------------------------------------------------+
//| Search of position of element in a sorted array |
//+------------------------------------------------------------------+
int CArrayInt::Search(const int element) const
{
int pos;
//--- check
if(m_data_total==0 || !IsSorted())
return(-1);
//--- search
pos=QuickSearch(element);
if(m_data[pos]==element)
return(pos);
//--- not found
return(-1);
}
//+------------------------------------------------------------------+
//| Search position of the first element which is greater than |
//| specified in a sorted array |
//+------------------------------------------------------------------+
int CArrayInt::SearchGreat(const int element) const
{
int pos;
//--- check
if(m_data_total==0 || !IsSorted())
return(-1);
//--- search
pos=QuickSearch(element);
while(m_data[pos]<=element)
if(++pos==m_data_total)
return(-1);
//--- position
return(pos);
}
//+------------------------------------------------------------------+
//| Search position of the first element which is less than |
//| specified in the sorted array |
//+------------------------------------------------------------------+
int CArrayInt::SearchLess(const int element) const
{
int pos;
//--- check
if(m_data_total==0 || !IsSorted())
return(-1);
//--- search
pos=QuickSearch(element);
while(m_data[pos]>=element)
if(pos--==0)
return(-1);
//--- position
return(pos);
}
//+------------------------------------------------------------------+
//| Search position of the first element which is greater than or |
//| equal to the specified in a sorted array |
//+------------------------------------------------------------------+
int CArrayInt::SearchGreatOrEqual(const int element) const
{
//--- check
if(m_data_total==0 || !IsSorted())
return(-1);
//--- search
for(int pos=QuickSearch(element);pos<m_data_total;pos++)
if(m_data[pos]>=element)
return(pos);
//--- not found
return(-1);
}
//+------------------------------------------------------------------+
//| Search position of the first element which is less than or equal |
//| to the specified in a sorted array |
//+------------------------------------------------------------------+
int CArrayInt::SearchLessOrEqual(const int element) const
{
//--- check
if(m_data_total==0 || !IsSorted())
return(-1);
//--- search
for(int pos=QuickSearch(element);pos>=0;pos--)
if(m_data[pos]<=element)
return(pos);
//--- not found
return(-1);
}
//+------------------------------------------------------------------+
//| Find position of first appearance of element in a sorted array |
//+------------------------------------------------------------------+
int CArrayInt::SearchFirst(const int element) const
{
int pos;
//--- check
if(m_data_total==0 || !IsSorted())
return(-1);
//--- search
pos=QuickSearch(element);
if(m_data[pos]==element)
{
while(m_data[pos]==element)
if(pos--==0)
break;
return(pos+1);
}
//--- not found
return(-1);
}
//+------------------------------------------------------------------+
//| Find position of last appearance of element in a sorted array |
//+------------------------------------------------------------------+
int CArrayInt::SearchLast(const int element) const
{
int pos;
//--- check
if(m_data_total==0 || !IsSorted())
return(-1);
//--- search
pos=QuickSearch(element);
if(m_data[pos]==element)
{
while(m_data[pos]==element)
if(++pos==m_data_total)
break;
return(pos-1);
}
//--- not found
return(-1);
}
//+------------------------------------------------------------------+
//| Writing array to file |
//+------------------------------------------------------------------+
bool CArrayInt::Save(const int file_handle)
{
int i=0;
//--- check
if(!CArray::Save(file_handle))
return(false);
//--- write array length
if(FileWriteInteger(file_handle,m_data_total,INT_VALUE)!=INT_VALUE)
return(false);
//--- write array
for(i=0;i<m_data_total;i++)
if(FileWriteInteger(file_handle,m_data[i],INT_VALUE)!=INT_VALUE)
break;
//--- result
return(i==m_data_total);
}
//+------------------------------------------------------------------+
//| Reading array from file |
//+------------------------------------------------------------------+
bool CArrayInt::Load(const int file_handle)
{
int i=0,num;
//--- check
if(!CArray::Load(file_handle))
return(false);
//--- read array length
num=FileReadInteger(file_handle,INT_VALUE);
//--- read array
Clear();
if(num!=0)
{
if(!Reserve(num))
return(false);
for(i=0;i<num;i++)
{
m_data[i]=FileReadInteger(file_handle,INT_VALUE);
m_data_total++;
if(FileIsEnding(file_handle))
break;
}
}
m_sort_mode=-1;
//--- result
return(m_data_total==num);
}
//+------------------------------------------------------------------+
+770
View File
@@ -0,0 +1,770 @@
//+------------------------------------------------------------------+
//| ArrayLong.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include "Array.mqh"
//+------------------------------------------------------------------+
//| Class CArrayLong. |
//| Purpose: Class of dynamic array of variables |
//| of long or ulong type. |
//| Derives from class CArray. |
//+------------------------------------------------------------------+
class CArrayLong : public CArray
{
protected:
long m_data[]; // data array
public:
CArrayLong(void);
~CArrayLong(void);
//--- method of identifying the object
virtual int Type(void) const { return(TYPE_LONG); }
//--- methods for working with files
virtual bool Save(const int file_handle);
virtual bool Load(const int file_handle);
//--- methods of managing dynamic memory
bool Reserve(const int size);
bool Resize(const int size);
bool Shutdown(void);
//--- methods of filling the array
bool Add(const long element);
bool AddArray(const long &src[]);
bool AddArray(const CArrayLong *src);
bool Insert(const long element,const int pos);
bool InsertArray(const long &src[],const int pos);
bool InsertArray(const CArrayLong *src,const int pos);
bool AssignArray(const long &src[]);
bool AssignArray(const CArrayLong *src);
//--- method of access to the array
long At(const int index) const;
long operator[](const int index) const { return(At(index)); }
//--- methods of searching for minimum and maximum
int Minimum(const int start,const int count) const { return(CArray::Minimum(m_data,start,count)); }
int Maximum(const int start,const int count) const { return(CArray::Maximum(m_data,start,count)); }
//--- methods change
bool Update(const int index,const long element);
bool Shift(const int index,const int shift);
//--- methods for deleting
bool Delete(const int index);
bool DeleteRange(int from,int to);
//--- methods for compare arrays
bool CompareArray(const long &array[]) const;
bool CompareArray(const CArrayLong *array) const;
//--- methods for working with the sorted array
bool InsertSort(const long element);
int Search(const long element) const;
int SearchGreat(const long element) const;
int SearchLess(const long element) const;
int SearchGreatOrEqual(const long element) const;
int SearchLessOrEqual(const long element) const;
int SearchFirst(const long element) const;
int SearchLast(const long element) const;
int SearchLinear(const long element) const;
protected:
virtual void QuickSort(int beg,int end,const int mode=0);
int QuickSearch(const long element) const;
int MemMove(const int dest,const int src,int count);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CArrayLong::CArrayLong(void)
{
//--- initialize protected data
m_data_max=ArraySize(m_data);
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CArrayLong::~CArrayLong(void)
{
if(m_data_max!=0)
Shutdown();
}
//+------------------------------------------------------------------+
//| Moving the memory within a single array |
//+------------------------------------------------------------------+
int CArrayLong::MemMove(const int dest,const int src,int count)
{
int i;
//--- check parameters
if(dest<0 || src<0 || count<0)
return(-1);
//--- check count
if(src+count>m_data_total)
count=m_data_total-src;
if(count<0)
return(-1);
//--- no need to copy
if(dest==src || count==0)
return(dest);
//--- check data total
if(dest+count>m_data_total)
{
if(m_data_max<dest+count)
return(-1);
m_data_total=dest+count;
}
//--- copy
if(dest<src)
{
//--- copy from left to right
for(i=0;i<count;i++)
m_data[dest+i]=m_data[src+i];
}
else
{
//--- copy from right to left
for(i=count-1;i>=0;i--)
m_data[dest+i]=m_data[src+i];
}
//--- successful
return(dest);
}
//+------------------------------------------------------------------+
//| Request for more memory in an array. Checks if the requested |
//| number of free elements already exists; allocates additional |
//| memory with a given step |
//+------------------------------------------------------------------+
bool CArrayLong::Reserve(const int size)
{
int new_size;
//--- check
if(size<=0)
return(false);
//--- resize array
if(Available()<size)
{
new_size=m_data_max+m_step_resize*(1+(size-Available())/m_step_resize);
if(new_size<0)
//--- overflow occurred when calculating new_size
return(false);
if((m_data_max=ArrayResize(m_data,new_size))==-1)
m_data_max=ArraySize(m_data);
}
//--- result
return(Available()>=size);
}
//+------------------------------------------------------------------+
//| Resizing (with removal of elements on the right) |
//+------------------------------------------------------------------+
bool CArrayLong::Resize(const int size)
{
int new_size;
//--- check
if(size<0)
return(false);
//--- resize array
new_size=m_step_resize*(1+size/m_step_resize);
if(m_data_max!=new_size)
{
if((m_data_max=ArrayResize(m_data,new_size))==-1)
{
m_data_max=ArraySize(m_data);
return(false);
}
}
if(m_data_total>size)
m_data_total=size;
//--- result
return(m_data_max==new_size);
}
//+------------------------------------------------------------------+
//| Complete cleaning of the array with the release of memory |
//+------------------------------------------------------------------+
bool CArrayLong::Shutdown(void)
{
//--- check
if(m_data_max==0)
return(true);
//--- clean
if(ArrayResize(m_data,0)==-1)
return(false);
m_data_total=0;
m_data_max=0;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Adding an element to the end of the array |
//+------------------------------------------------------------------+
bool CArrayLong::Add(const long element)
{
//--- check/reserve elements of array
if(!Reserve(1))
return(false);
//--- add
m_data[m_data_total++]=element;
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Adding an element to the end of the array from another array |
//+------------------------------------------------------------------+
bool CArrayLong::AddArray(const long &src[])
{
int num=ArraySize(src);
//--- check/reserve elements of array
if(!Reserve(num))
return(false);
//--- add
for(int i=0;i<num;i++)
m_data[m_data_total++]=src[i];
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Adding an element to the end of the array from another array |
//+------------------------------------------------------------------+
bool CArrayLong::AddArray(const CArrayLong *src)
{
int num;
//--- check
if(!CheckPointer(src))
return(false);
//--- check/reserve elements of array
num=src.Total();
if(!Reserve(num))
return(false);
//--- add
for(int i=0;i<num;i++)
m_data[m_data_total++]=src.m_data[i];
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Inserting an element in the specified position |
//+------------------------------------------------------------------+
bool CArrayLong::Insert(const long element,const int pos)
{
//--- check/reserve elements of array
if(pos<0 || !Reserve(1))
return(false);
//--- insert
m_data_total++;
if(pos<m_data_total-1)
{
if(MemMove(pos+1,pos,m_data_total-pos-1)<0)
return(false);
m_data[pos]=element;
}
else
m_data[m_data_total-1]=element;
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Inserting elements in the specified position |
//+------------------------------------------------------------------+
bool CArrayLong::InsertArray(const long &src[],const int pos)
{
int num=ArraySize(src);
//--- check/reserve elements of array
if(!Reserve(num))
return(false);
//--- insert
if(MemMove(num+pos,pos,m_data_total-pos)<0)
return(false);
for(int i=0;i<num;i++)
m_data[i+pos]=src[i];
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Inserting elements in the specified position |
//+------------------------------------------------------------------+
bool CArrayLong::InsertArray(const CArrayLong *src,const int pos)
{
int num;
//--- check
if(!CheckPointer(src))
return(false);
//--- check/reserve elements of array
num=src.Total();
if(!Reserve(num))
return(false);
//--- insert
if(MemMove(num+pos,pos,m_data_total-pos)<0)
return(false);
for(int i=0;i<num;i++)
m_data[i+pos]=src.m_data[i];
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Assignment (copying) of another array |
//+------------------------------------------------------------------+
bool CArrayLong::AssignArray(const long &src[])
{
int num=ArraySize(src);
//--- check/reserve elements of array
Clear();
if(m_data_max<num)
{
if(!Reserve(num))
return(false);
}
else
Resize(num);
//--- copy array
for(int i=0;i<num;i++)
{
m_data[i]=src[i];
m_data_total++;
}
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Assignment (copying) of another array |
//+------------------------------------------------------------------+
bool CArrayLong::AssignArray(const CArrayLong *src)
{
int num;
//--- check
if(!CheckPointer(src))
return(false);
//--- check/reserve elements of array
num=src.m_data_total;
Clear();
if(m_data_max<num)
{
if(!Reserve(num))
return(false);
}
else
Resize(num);
//--- copy array
for(int i=0;i<num;i++)
{
m_data[i]=src.m_data[i];
m_data_total++;
}
m_sort_mode=src.SortMode();
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Access to data in the specified position |
//+------------------------------------------------------------------+
long CArrayLong::At(const int index) const
{
//--- check
if(index<0 || index>=m_data_total)
return(LONG_MAX);
//--- result
return(m_data[index]);
}
//+------------------------------------------------------------------+
//| Updating element in the specified position |
//+------------------------------------------------------------------+
bool CArrayLong::Update(const int index,const long element)
{
//--- check
if(index<0 || index>=m_data_total)
return(false);
//--- update
m_data[index]=element;
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Moving element from the specified position |
//| on the specified shift |
//+------------------------------------------------------------------+
bool CArrayLong::Shift(const int index,const int shift)
{
long tmp_long;
//--- check
if(index<0 || index+shift<0 || index+shift>=m_data_total)
return(false);
if(shift==0)
return(true);
//--- move
tmp_long=m_data[index];
if(shift>0)
{
if(MemMove(index,index+1,shift)<0)
return(false);
}
else
{
if(MemMove(index+shift+1,index+shift,-shift)<0)
return(false);
}
m_data[index+shift]=tmp_long;
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Deleting element from the specified position |
//+------------------------------------------------------------------+
bool CArrayLong::Delete(const int index)
{
//--- check
if(index<0 || index>=m_data_total)
return(false);
//--- delete
if(index<m_data_total-1 && MemMove(index,index+1,m_data_total-index-1)<0)
return(false);
m_data_total--;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Deleting range of elements |
//+------------------------------------------------------------------+
bool CArrayLong::DeleteRange(int from,int to)
{
//--- check
if(from<0 || to<0)
return(false);
if(from>to || from>=m_data_total)
return(false);
//--- delete
if(to>=m_data_total-1)
to=m_data_total-1;
if(MemMove(from,to+1,m_data_total-to-1)<0)
return(false);
m_data_total-=to-from+1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Equality comparison of two arrays |
//+------------------------------------------------------------------+
bool CArrayLong::CompareArray(const long &array[]) const
{
//--- compare
if(m_data_total!=ArraySize(array))
return(false);
for(int i=0;i<m_data_total;i++)
if(m_data[i]!=array[i])
return(false);
//--- equal
return(true);
}
//+------------------------------------------------------------------+
//| Equality comparison of two arrays |
//+------------------------------------------------------------------+
bool CArrayLong::CompareArray(const CArrayLong *array) const
{
//--- check
if(!CheckPointer(array))
return(false);
//--- compare
if(m_data_total!=array.m_data_total)
return(false);
for(int i=0;i<m_data_total;i++)
if(m_data[i]!=array.m_data[i])
return(false);
//--- equal
return(true);
}
//+------------------------------------------------------------------+
//| Method QuickSort |
//+------------------------------------------------------------------+
void CArrayLong::QuickSort(int beg,int end,const int mode)
{
int i,j;
long p_long,t_long;
//--- check
if(beg<0 || end<0)
return;
//--- sort
i=beg;
j=end;
while(i<end)
{
//--- ">>1" is quick division by 2
p_long=m_data[(beg+end)>>1];
while(i<j)
{
while(m_data[i]<p_long)
{
//--- control the output of the array bounds
if(i==m_data_total-1)
break;
i++;
}
while(m_data[j]>p_long)
{
//--- control the output of the array bounds
if(j==0)
break;
j--;
}
if(i<=j)
{
t_long=m_data[i];
m_data[i++]=m_data[j];
m_data[j]=t_long;
//--- control the output of the array bounds
if(j==0)
break;
j--;
}
}
if(beg<j)
QuickSort(beg,j);
beg=i;
j=end;
}
}
//+------------------------------------------------------------------+
//| Inserting element in a sorted array |
//+------------------------------------------------------------------+
bool CArrayLong::InsertSort(const long element)
{
int pos;
//--- check
if(!IsSorted())
return(false);
//--- check/reserve elements of array
if(!Reserve(1))
return(false);
//--- if the array is empty, add an element
if(m_data_total==0)
{
m_data[m_data_total++]=element;
return(true);
}
//--- search position and insert
pos=QuickSearch(element);
if(m_data[pos]>element)
Insert(element,pos);
else
Insert(element,pos+1);
//--- restore the sorting flag after Insert(...)
m_sort_mode=0;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Search of position of element in a array |
//+------------------------------------------------------------------+
int CArrayLong::SearchLinear(const long element) const
{
//--- check
if(m_data_total==0)
return(-1);
//---
for(int i=0;i<m_data_total;i++)
if(m_data[i]==element)
return(i);
//--- not found
return(-1);
}
//+------------------------------------------------------------------+
//| Quick search of position of element in a sorted array |
//+------------------------------------------------------------------+
int CArrayLong::QuickSearch(const long element) const
{
int i,j,m=-1;
long t_long;
//--- search
i=0;
j=m_data_total-1;
while(j>=i)
{
//--- ">>1" is quick division by 2
m=(j+i)>>1;
if(m<0 || m>=m_data_total)
break;
t_long=m_data[m];
if(t_long==element)
break;
if(t_long>element)
j=m-1;
else
i=m+1;
}
//--- position
return(m);
}
//+------------------------------------------------------------------+
//| Search of position of element in a sorted array |
//+------------------------------------------------------------------+
int CArrayLong::Search(const long element) const
{
int pos;
//--- check
if(m_data_total==0 || !IsSorted())
return(-1);
//--- search
pos=QuickSearch(element);
if(m_data[pos]==element)
return(pos);
//--- not found
return(-1);
}
//+------------------------------------------------------------------+
//| Search position of the first element which is greater than |
//| specified in a sorted array |
//+------------------------------------------------------------------+
int CArrayLong::SearchGreat(const long element) const
{
int pos;
//--- check
if(m_data_total==0 || !IsSorted())
return(-1);
//--- search
pos=QuickSearch(element);
while(m_data[pos]<=element)
if(++pos==m_data_total)
return(-1);
//--- position
return(pos);
}
//+------------------------------------------------------------------+
//| Search position of the first element which is less than |
//| specified in the sorted array |
//+------------------------------------------------------------------+
int CArrayLong::SearchLess(const long element) const
{
int pos;
//--- check
if(m_data_total==0 || !IsSorted())
return(-1);
//--- search
pos=QuickSearch(element);
while(m_data[pos]>=element)
if(pos--==0)
return(-1);
//--- position
return(pos);
}
//+------------------------------------------------------------------+
//| Search position of the first element which is greater than or |
//| equal to the specified in a sorted array |
//+------------------------------------------------------------------+
int CArrayLong::SearchGreatOrEqual(const long element) const
{
//--- check
if(m_data_total==0 || !IsSorted())
return(-1);
//--- search
for(int pos=QuickSearch(element);pos<m_data_total;pos++)
if(m_data[pos]>=element)
return(pos);
//--- not found
return(-1);
}
//+------------------------------------------------------------------+
//| Search position of the first element which is less than or equal |
//| to the specified in a sorted array |
//+------------------------------------------------------------------+
int CArrayLong::SearchLessOrEqual(const long element) const
{
//--- check
if(m_data_total==0 || !IsSorted())
return(-1);
//--- search
for(int pos=QuickSearch(element);pos>=0;pos--)
if(m_data[pos]<=element)
return(pos);
//--- not found
return(-1);
}
//+------------------------------------------------------------------+
//| Find position of first appearance of element in a sorted array |
//+------------------------------------------------------------------+
int CArrayLong::SearchFirst(const long element) const
{
int pos;
//--- check
if(m_data_total==0 || !IsSorted())
return(-1);
//--- search
pos=QuickSearch(element);
if(m_data[pos]==element)
{
while(m_data[pos]==element)
if(pos--==0)
break;
return(pos+1);
}
//--- not found
return(-1);
}
//+------------------------------------------------------------------+
//| Find position of last appearance of element in a sorted array |
//+------------------------------------------------------------------+
int CArrayLong::SearchLast(const long element) const
{
int pos;
//--- check
if(m_data_total==0 || !IsSorted())
return(-1);
//--- search
pos=QuickSearch(element);
if(m_data[pos]==element)
{
while(m_data[pos]==element)
if(++pos==m_data_total)
break;
return(pos-1);
}
//--- not found
return(-1);
}
//+------------------------------------------------------------------+
//| Writing array to file |
//+------------------------------------------------------------------+
bool CArrayLong::Save(const int file_handle)
{
int i=0;
//--- check
if(!CArray::Save(file_handle))
return(false);
//--- write array length
if(FileWriteInteger(file_handle,m_data_total,INT_VALUE)!=INT_VALUE)
return(false);
//--- write array
for(i=0;i<m_data_total;i++)
if(FileWriteLong(file_handle,m_data[i])!=sizeof(long))
break;
//--- result
return(i==m_data_total);
}
//+------------------------------------------------------------------+
//| Reading array from file |
//+------------------------------------------------------------------+
bool CArrayLong::Load(const int file_handle)
{
int i=0,num;
//--- check
if(!CArray::Load(file_handle))
return(false);
//--- read array length
num=FileReadInteger(file_handle,INT_VALUE);
//--- read array
Clear();
if(num!=0)
{
if(!Reserve(num))
return(false);
for(i=0;i<num;i++)
{
m_data[i]=FileReadLong(file_handle);
m_data_total++;
if(FileIsEnding(file_handle))
break;
}
}
m_sort_mode=-1;
//--- result
return(m_data_total==num);
}
//+------------------------------------------------------------------+
+759
View File
@@ -0,0 +1,759 @@
//+------------------------------------------------------------------+
//| ArrayObj.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include "Array.mqh"
//+------------------------------------------------------------------+
//| Class CArrayObj. |
//| Puprose: Class of dynamic array of pointers to instances |
//| of the CObject class and its derivatives. |
//| Derives from class CArray. |
//+------------------------------------------------------------------+
class CArrayObj : public CArray
{
protected:
CObject *m_data[]; // data array
bool m_free_mode; // flag of necessity of "physical" deletion of object
public:
CArrayObj(void);
~CArrayObj(void);
//--- methods of access to protected data
bool FreeMode(void) const { return(m_free_mode); }
void FreeMode(const bool mode) { m_free_mode=mode; }
//--- method of identifying the object
virtual int Type(void) const { return(0x7778); }
//--- methods for working with files
virtual bool Save(const int file_handle);
virtual bool Load(const int file_handle);
//--- method of creating an element of array
virtual bool CreateElement(const int index) { return(false); }
//--- methods of managing dynamic memory
bool Reserve(const int size);
bool Resize(const int size);
bool Shutdown(void);
//--- methods of filling the array
bool Add(CObject *element);
bool AddArray(const CArrayObj *src);
bool Insert(CObject *element,const int pos);
bool InsertArray(const CArrayObj *src,const int pos);
bool AssignArray(const CArrayObj *src);
//--- method of access to thre array
CObject *At(const int index) const;
//--- methods of changing
bool Update(const int index,CObject *element);
bool Shift(const int index,const int shift);
//--- methods of deleting
CObject *Detach(const int index);
bool Delete(const int index);
bool DeleteRange(int from,int to);
void Clear(void);
//--- method for comparing arrays
bool CompareArray(const CArrayObj *array) const;
//--- methods for working with the sorted array
bool InsertSort(CObject *element);
int Search(const CObject *element) const;
int SearchGreat(const CObject *element) const;
int SearchLess(const CObject *element) const;
int SearchGreatOrEqual(const CObject *element) const;
int SearchLessOrEqual(const CObject *element) const;
int SearchFirst(const CObject *element) const;
int SearchLast(const CObject *element) const;
protected:
void QuickSort(int beg,int end,const int mode);
int QuickSearch(const CObject *element) const;
int MemMove(const int dest,const int src,int count);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CArrayObj::CArrayObj(void) : m_free_mode(true)
{
//--- initialize protected data
m_data_max=ArraySize(m_data);
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CArrayObj::~CArrayObj(void)
{
if(m_data_max!=0)
Shutdown();
}
//+------------------------------------------------------------------+
//| Moving the memory within a single array |
//+------------------------------------------------------------------+
int CArrayObj::MemMove(const int dest,const int src,int count)
{
int i;
//--- check parameters
if(dest<0 || src<0 || count<0)
return(-1);
//--- check count
if(src+count>m_data_total)
count=m_data_total-src;
if(count<0)
return(-1);
//--- no need to copy
if(dest==src || count==0)
return(dest);
//--- check data total
if(dest+count>m_data_total)
{
if(m_data_max<dest+count)
return(-1);
m_data_total=dest+count;
}
//--- copy
if(dest<src)
{
//--- copy from left to right
for(i=0;i<count;i++)
{
//--- "physical" removal of the object (if necessary and possible)
if(m_free_mode && CheckPointer(m_data[dest+i])==POINTER_DYNAMIC)
delete m_data[dest+i];
//---
m_data[dest+i]=m_data[src+i];
m_data[src+i]=NULL;
}
}
else
{
//--- copy from right to left
for(i=count-1;i>=0;i--)
{
//--- "physical" removal of the object (if necessary and possible)
if(m_free_mode && CheckPointer(m_data[dest+i])==POINTER_DYNAMIC)
delete m_data[dest+i];
//---
m_data[dest+i]=m_data[src+i];
m_data[src+i]=NULL;
}
}
//--- successful
return(dest);
}
//+------------------------------------------------------------------+
//| Request for more memory in an array. Checks if the requested |
//| number of free elements already exists; allocates additional |
//| memory with a given step |
//+------------------------------------------------------------------+
bool CArrayObj::Reserve(const int size)
{
int new_size;
//--- check
if(size<=0)
return(false);
//--- resize array
if(Available()<size)
{
new_size=m_data_max+m_step_resize*(1+(size-Available())/m_step_resize);
if(new_size<0)
//--- overflow occurred when calculating new_size
return(false);
if((m_data_max=ArrayResize(m_data,new_size))==-1)
m_data_max=ArraySize(m_data);
//--- explicitly zeroize all the loose items in the array
for(int i=m_data_total;i<m_data_max;i++)
m_data[i]=NULL;
}
//--- result
return(Available()>=size);
}
//+------------------------------------------------------------------+
//| Resizing (with removal of elements on the right) |
//+------------------------------------------------------------------+
bool CArrayObj::Resize(const int size)
{
int new_size;
//--- check
if(size<0)
return(false);
//--- resize array
new_size=m_step_resize*(1+size/m_step_resize);
if(m_data_total>size)
{
//--- "physical" removal of the object (if necessary and possible)
if(m_free_mode)
for(int i=size;i<m_data_total;i++)
if(CheckPointer(m_data[i])==POINTER_DYNAMIC)
delete m_data[i];
m_data_total=size;
}
if(m_data_max!=new_size)
{
if((m_data_max=ArrayResize(m_data,new_size))==-1)
{
m_data_max=ArraySize(m_data);
return(false);
}
}
//--- result
return(m_data_max==new_size);
}
//+------------------------------------------------------------------+
//| Complete cleaning of the array with the release of memory |
//+------------------------------------------------------------------+
bool CArrayObj::Shutdown(void)
{
//--- check
if(m_data_max==0)
return(true);
//--- clean
Clear();
if(ArrayResize(m_data,0)==-1)
return(false);
m_data_max=0;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Adding an element to the end of the array |
//+------------------------------------------------------------------+
bool CArrayObj::Add(CObject *element)
{
//--- check
if(!CheckPointer(element))
return(false);
//--- check/reserve elements of array
if(!Reserve(1))
return(false);
//--- add
m_data[m_data_total++]=element;
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Adding an element to the end of the array from another array |
//+------------------------------------------------------------------+
bool CArrayObj::AddArray(const CArrayObj *src)
{
int num;
//--- check
if(!CheckPointer(src))
return(false);
//--- check/reserve elements of array
num=src.Total();
if(!Reserve(num))
return(false);
//--- add
for(int i=0;i<num;i++)
m_data[m_data_total++]=src.m_data[i];
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Inserting an element in the specified position |
//+------------------------------------------------------------------+
bool CArrayObj::Insert(CObject *element,const int pos)
{
//--- check
if(pos<0 || !CheckPointer(element))
return(false);
//--- check/reserve elements of array
if(!Reserve(1))
return(false);
//--- insert
m_data_total++;
if(pos<m_data_total-1)
{
if(MemMove(pos+1,pos,m_data_total-pos-1)<0)
return(false);
m_data[pos]=element;
}
else
m_data[m_data_total-1]=element;
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Inserting elements in the specified position |
//+------------------------------------------------------------------+
bool CArrayObj::InsertArray(const CArrayObj *src,const int pos)
{
int num;
//--- check
if(!CheckPointer(src))
return(false);
//--- check/reserve elements of array
num=src.Total();
if(!Reserve(num)) return(false);
//--- insert
if(MemMove(num+pos,pos,m_data_total-pos)<0)
return(false);
for(int i=0;i<num;i++)
m_data[i+pos]=src.m_data[i];
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Assignment (copying) of another array |
//+------------------------------------------------------------------+
bool CArrayObj::AssignArray(const CArrayObj *src)
{
int num;
//--- check
if(!CheckPointer(src))
return(false);
//--- check/reserve elements of array
num=src.m_data_total;
Clear();
if(m_data_max<num)
{
if(!Reserve(num))
return(false);
}
else
Resize(num);
//--- copy array
for(int i=0;i<num;i++)
{
m_data[i]=src.m_data[i];
m_data_total++;
}
m_sort_mode=src.SortMode();
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Access to data in the specified position |
//+------------------------------------------------------------------+
CObject *CArrayObj::At(const int index) const
{
//--- check
if(index<0 || index>=m_data_total)
return(NULL);
//--- result
return(m_data[index]);
}
//+------------------------------------------------------------------+
//| Updating element in the specified position |
//+------------------------------------------------------------------+
bool CArrayObj::Update(const int index,CObject *element)
{
//--- check
if(index<0 || !CheckPointer(element) || index>=m_data_total)
return(false);
//--- "physical" removal of the object (if necessary and possible)
if(m_free_mode && CheckPointer(m_data[index])==POINTER_DYNAMIC)
delete m_data[index];
//--- update
m_data[index]=element;
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Moving element from the specified position |
//| on the specified shift |
//+------------------------------------------------------------------+
bool CArrayObj::Shift(const int index,const int shift)
{
CObject *tmp_node;
//--- check
if(index<0 || index+shift<0 || index+shift>=m_data_total)
return(false);
if(shift==0)
return(true);
//--- move
tmp_node=m_data[index];
m_data[index]=NULL;
if(shift>0)
{
if(MemMove(index,index+1,shift)<0)
return(false);
}
else
{
if(MemMove(index+shift+1,index+shift,-shift)<0)
return(false);
}
m_data[index+shift]=tmp_node;
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Deleting element from the specified position |
//+------------------------------------------------------------------+
bool CArrayObj::Delete(const int index)
{
//--- check
if(index>=m_data_total)
return(false);
//--- delete
if(index<m_data_total-1)
{
if(index>=0 && MemMove(index,index+1,m_data_total-index-1)<0)
return(false);
}
else
if(m_free_mode && CheckPointer(m_data[index])==POINTER_DYNAMIC)
delete m_data[index];
m_data_total--;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Detach element from the specified position |
//+------------------------------------------------------------------+
CObject *CArrayObj::Detach(const int index)
{
CObject *result;
//--- check
if(index>=m_data_total)
return(NULL);
//--- detach
result=m_data[index];
//--- reset the array element, so as not remove the method MemMove
m_data[index]=NULL;
if(index<m_data_total-1 && MemMove(index,index+1,m_data_total-index-1)<0)
return(NULL);
m_data_total--;
//--- successful
return(result);
}
//+------------------------------------------------------------------+
//| Deleting range of elements |
//+------------------------------------------------------------------+
bool CArrayObj::DeleteRange(int from,int to)
{
//--- check
if(from<0 || to<0)
return(false);
if(from>to || from>=m_data_total)
return(false);
//--- delete
if(to>=m_data_total-1)
to=m_data_total-1;
if(MemMove(from,to+1,m_data_total-to-1)<0)
return(false);
for(int i=to-from+1;i>0;i--,m_data_total--)
if(m_free_mode && CheckPointer(m_data[m_data_total-1])==POINTER_DYNAMIC)
delete m_data[m_data_total-1];
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Clearing of array without the release of memory |
//+------------------------------------------------------------------+
void CArrayObj::Clear(void)
{
//--- "physical" removal of the object (if necessary and possible)
if(m_free_mode)
{
for(int i=0;i<m_data_total;i++)
{
if(CheckPointer(m_data[i])==POINTER_DYNAMIC)
delete m_data[i];
m_data[i]=NULL;
}
}
m_data_total=0;
}
//+------------------------------------------------------------------+
//| Equality comparison of two arrays |
//+------------------------------------------------------------------+
bool CArrayObj::CompareArray(const CArrayObj *array) const
{
//--- check
if(!CheckPointer(array))
return(false);
//--- compare
if(m_data_total!=array.m_data_total)
return(false);
for(int i=0;i<m_data_total;i++)
if(m_data[i].Compare(array.m_data[i],0)!=0)
return(false);
//--- equal
return(true);
}
//+------------------------------------------------------------------+
//| Method QuickSort |
//+------------------------------------------------------------------+
void CArrayObj::QuickSort(int beg,int end,const int mode)
{
int i,j;
CObject *p_node;
CObject *t_node;
//--- sort
i=beg;
j=end;
while(i<end)
{
//--- ">>1" is quick division by 2
p_node=m_data[(beg+end)>>1];
while(i<j)
{
while(m_data[i].Compare(p_node,mode)<0)
{
//--- control the output of the array bounds
if(i==m_data_total-1)
break;
i++;
}
while(m_data[j].Compare(p_node,mode)>0)
{
//--- control the output of the array bounds
if(j==0)
break;
j--;
}
if(i<=j)
{
t_node=m_data[i];
m_data[i++]=m_data[j];
m_data[j]=t_node;
//--- control the output of the array bounds
if(j==0)
break;
j--;
}
}
if(beg<j)
QuickSort(beg,j,mode);
beg=i;
j=end;
}
}
//+------------------------------------------------------------------+
//| Inserting element in a sorted array |
//+------------------------------------------------------------------+
bool CArrayObj::InsertSort(CObject *element)
{
int pos;
//--- check
if(!CheckPointer(element) || m_sort_mode==-1)
return(false);
//--- check/reserve elements of array
if(!Reserve(1))
return(false);
//--- if the array is empty, add an element
if(m_data_total==0)
{
m_data[m_data_total++]=element;
return(true);
}
//--- find position and insert
int mode=m_sort_mode;
pos=QuickSearch(element);
if(m_data[pos].Compare(element,m_sort_mode)>0)
Insert(element,pos);
else
Insert(element,pos+1);
//--- restore the sorting flag after Insert(...)
m_sort_mode=mode;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Quick search of position of element in a sorted array |
//+------------------------------------------------------------------+
int CArrayObj::QuickSearch(const CObject *element) const
{
int i,j,m=-1;
CObject *t_node;
//--- search
i=0;
j=m_data_total-1;
while(j>=i)
{
//--- ">>1" is quick division by 2
m=(j+i)>>1;
if(m<0 || m==m_data_total-1)
break;
t_node=m_data[m];
if(t_node.Compare(element,m_sort_mode)==0)
break;
if(t_node.Compare(element,m_sort_mode)>0)
j=m-1;
else
i=m+1;
}
//--- position
return(m);
}
//+------------------------------------------------------------------+
//| Search of position of element in a sorted array |
//+------------------------------------------------------------------+
int CArrayObj::Search(const CObject *element) const
{
int pos;
//--- check
if(m_data_total==0 || !CheckPointer(element) || m_sort_mode==-1)
return(-1);
//--- search
pos=QuickSearch(element);
if(m_data[pos].Compare(element,m_sort_mode)==0)
return(pos);
//--- not found
return(-1);
}
//+------------------------------------------------------------------+
//| Search position of the first element which is greater than |
//| specified in a sorted array |
//+------------------------------------------------------------------+
int CArrayObj::SearchGreat(const CObject *element) const
{
int pos;
//--- check
if(m_data_total==0 || !CheckPointer(element) || m_sort_mode==-1)
return(-1);
//--- search
pos=QuickSearch(element);
while(m_data[pos].Compare(element,m_sort_mode)<=0)
if(++pos==m_data_total)
return(-1);
//--- position
return(pos);
}
//+------------------------------------------------------------------+
//| Search position of the first element which is less than |
//| specified in the sorted array |
//+------------------------------------------------------------------+
int CArrayObj::SearchLess(const CObject *element) const
{
int pos;
//--- check
if(m_data_total==0 || !CheckPointer(element) || m_sort_mode==-1)
return(-1);
//--- search
pos=QuickSearch(element);
while(m_data[pos].Compare(element,m_sort_mode)>=0)
if(pos--==0)
return(-1);
//--- position
return(pos);
}
//+------------------------------------------------------------------+
//| Search position of the first element which is greater than or |
//| equal to the specified in a sorted array |
//+------------------------------------------------------------------+
int CArrayObj::SearchGreatOrEqual(const CObject *element) const
{
//--- check
if(m_data_total==0 || !CheckPointer(element) || m_sort_mode==-1)
return(-1);
//--- search
for(int pos=QuickSearch(element);pos<m_data_total;pos++)
if(m_data[pos].Compare(element,m_sort_mode)>=0)
return(pos);
//--- not found
return(-1);
}
//+------------------------------------------------------------------+
//| Search position of the first element which is less than or equal |
//| to the specified in a sorted array |
//+------------------------------------------------------------------+
int CArrayObj::SearchLessOrEqual(const CObject *element) const
{
//--- check
if(m_data_total==0 || !CheckPointer(element) || m_sort_mode==-1)
return(-1);
//--- search
for(int pos=QuickSearch(element);pos>=0;pos--)
if(m_data[pos].Compare(element,m_sort_mode)<=0)
return(pos);
//--- not found
return(-1);
}
//+------------------------------------------------------------------+
//| Find position of first appearance of element in a sorted array |
//+------------------------------------------------------------------+
int CArrayObj::SearchFirst(const CObject *element) const
{
int pos;
//--- check
if(m_data_total==0 || !CheckPointer(element) || m_sort_mode==-1)
return(-1);
//--- search
pos=QuickSearch(element);
if(m_data[pos].Compare(element,m_sort_mode)==0)
{
while(m_data[pos].Compare(element,m_sort_mode)==0)
if(pos--==0)
break;
return(pos+1);
}
//--- not found
return(-1);
}
//+------------------------------------------------------------------+
//| Find position of last appearance of element in a sorted array |
//+------------------------------------------------------------------+
int CArrayObj::SearchLast(const CObject *element) const
{
int pos;
//--- check
if(m_data_total==0 || !CheckPointer(element) || m_sort_mode==-1)
return(-1);
//--- search
pos=QuickSearch(element);
if(m_data[pos].Compare(element,m_sort_mode)==0)
{
while(m_data[pos].Compare(element,m_sort_mode)==0)
if(++pos==m_data_total)
break;
return(pos-1);
}
//--- not found
return(-1);
}
//+------------------------------------------------------------------+
//| Writing array to file |
//+------------------------------------------------------------------+
bool CArrayObj::Save(const int file_handle)
{
int i=0;
//--- check
if(!CArray::Save(file_handle))
return(false);
//--- write array length
if(FileWriteInteger(file_handle,m_data_total,INT_VALUE)!=INT_VALUE)
return(false);
//--- write array
for(i=0;i<m_data_total;i++)
if(m_data[i].Save(file_handle)!=true)
break;
//--- result
return(i==m_data_total);
}
//+------------------------------------------------------------------+
//| Reading array from file |
//+------------------------------------------------------------------+
bool CArrayObj::Load(const int file_handle)
{
int i=0,num;
//--- check
if(!CArray::Load(file_handle))
return(false);
//--- read array length
num=FileReadInteger(file_handle,INT_VALUE);
//--- read array
Clear();
if(num!=0)
{
if(!Reserve(num))
return(false);
for(i=0;i<num;i++)
{
//--- create new element
if(!CreateElement(i))
break;
if(m_data[i].Load(file_handle)!=true)
break;
m_data_total++;
}
}
m_sort_mode=-1;
//--- result
return(m_data_total==num);
}
//+------------------------------------------------------------------+
+770
View File
@@ -0,0 +1,770 @@
//+------------------------------------------------------------------+
//| ArrayShort.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include "Array.mqh"
//+------------------------------------------------------------------+
//| Class CArrayShort. |
//| Pupose: Class of dynamic array of variables |
//| of short or ushort type. |
//| Derives from class CArray. |
//+------------------------------------------------------------------+
class CArrayShort : public CArray
{
protected:
short m_data[]; // data array
public:
CArrayShort(void);
~CArrayShort(void);
//--- method of identifying the object
virtual int Type(void) const { return(TYPE_SHORT); }
//--- methods for working with files
virtual bool Save(const int file_handle);
virtual bool Load(const int file_handle);
//--- methods of managing dynamic memory
bool Reserve(const int size);
bool Resize(const int size);
bool Shutdown(void);
//--- methods of filling the array
bool Add(const short element);
bool AddArray(const short &src[]);
bool AddArray(const CArrayShort *src);
bool Insert(const short element,const int pos);
bool InsertArray(const short &src[],const int pos);
bool InsertArray(const CArrayShort *src,const int pos);
bool AssignArray(const short &src[]);
bool AssignArray(const CArrayShort *src);
//--- method of access to the array
short At(const int index) const;
short operator[](const int index) const { return(At(index)); }
//--- methods of searching for minimum and maximum
int Minimum(const int start,const int count) const { return(CArray::Minimum(m_data,start,count)); }
int Maximum(const int start,const int count) const { return(CArray::Maximum(m_data,start,count)); }
//--- methods of changing
bool Update(const int index,const short element);
bool Shift(const int index,const int shift);
//--- methods of deleting
bool Delete(const int index);
bool DeleteRange(int from,int to);
//--- methods for comparing arrays
bool CompareArray(const short &array[]) const;
bool CompareArray(const CArrayShort *array) const;
//--- methods for working with the sorted array
bool InsertSort(const short element);
int Search(const short element) const;
int SearchGreat(const short element) const;
int SearchLess(const short element) const;
int SearchGreatOrEqual(const short element) const;
int SearchLessOrEqual(const short element) const;
int SearchFirst(const short element) const;
int SearchLast(const short element) const;
int SearchLinear(const short element) const;
protected:
virtual void QuickSort(int beg,int end,const int mode=0);
int QuickSearch(const short element) const;
int MemMove(const int dest,const int src,int count);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CArrayShort::CArrayShort(void)
{
//--- initialize protected data
m_data_max=ArraySize(m_data);
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CArrayShort::~CArrayShort(void)
{
if(m_data_max!=0)
Shutdown();
}
//+------------------------------------------------------------------+
//| Moving the memory within a single array |
//+------------------------------------------------------------------+
int CArrayShort::MemMove(const int dest,const int src,int count)
{
int i;
//--- check parameters
if(dest<0 || src<0 || count<0)
return(-1);
//--- check count
if(src+count>m_data_total)
count=m_data_total-src;
if(count<0)
return(-1);
//--- no need to copy
if(dest==src || count==0)
return(dest);
//--- check data total
if(dest+count>m_data_total)
{
if(m_data_max<dest+count)
return(-1);
m_data_total=dest+count;
}
//--- copy
if(dest<src)
{
//--- copy from left to right
for(i=0;i<count;i++)
m_data[dest+i]=m_data[src+i];
}
else
{
//--- copy from right to left
for(i=count-1;i>=0;i--)
m_data[dest+i]=m_data[src+i];
}
//--- successful
return(dest);
}
//+------------------------------------------------------------------+
//| Request for more memory in an array. Checks if the requested |
//| number of free elements already exists; allocates additional |
//| memory with a given step |
//+------------------------------------------------------------------+
bool CArrayShort::Reserve(const int size)
{
int new_size;
//--- check
if(size<=0)
return(false);
//--- resize array
if(Available()<size)
{
new_size=m_data_max+m_step_resize*(1+(size-Available())/m_step_resize);
if(new_size<0)
//--- overflow occurred when calculating new_size
return(false);
if((m_data_max=ArrayResize(m_data,new_size))==-1)
m_data_max=ArraySize(m_data);
}
//--- result
return(Available()>=size);
}
//+------------------------------------------------------------------+
//| Resizing (with removal of elements on the right) |
//+------------------------------------------------------------------+
bool CArrayShort::Resize(const int size)
{
int new_size;
//--- check
if(size<0)
return(false);
//--- resize array
new_size=m_step_resize*(1+size/m_step_resize);
if(m_data_max!=new_size)
{
if((m_data_max=ArrayResize(m_data,new_size))==-1)
{
m_data_max=ArraySize(m_data);
return(false);
}
}
if(m_data_total>size)
m_data_total=size;
//--- result
return(m_data_max==new_size);
}
//+------------------------------------------------------------------+
//| Complete cleaning of the array with the release of memory |
//+------------------------------------------------------------------+
bool CArrayShort::Shutdown(void)
{
//--- check
if(m_data_max==0)
return(true);
//--- clean
if(ArrayResize(m_data,0)==-1)
return(false);
m_data_total=0;
m_data_max=0;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Adding an element to the end of the array |
//+------------------------------------------------------------------+
bool CArrayShort::Add(const short element)
{
//--- check/reserve elements of array
if(!Reserve(1))
return(false);
//--- add
m_data[m_data_total++]=element;
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Adding an element to the end of the array from another array |
//+------------------------------------------------------------------+
bool CArrayShort::AddArray(const short &src[])
{
int num=ArraySize(src);
//--- check/reserve elements of array
if(!Reserve(num))
return(false);
//--- add
for(int i=0;i<num;i++)
m_data[m_data_total++]=src[i];
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Adding an element to the end of the array from another array |
//+------------------------------------------------------------------+
bool CArrayShort::AddArray(const CArrayShort *src)
{
int num;
//--- check
if(!CheckPointer(src))
return(false);
//--- check/reserve elements of array
num=src.Total();
if(!Reserve(num))
return(false);
//--- add
for(int i=0;i<num;i++)
m_data[m_data_total++]=src.m_data[i];
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Inserting an element in the specified position |
//+------------------------------------------------------------------+
bool CArrayShort::Insert(const short element,const int pos)
{
//--- check/reserve elements of array
if(pos<0 || !Reserve(1))
return(false);
//--- insert
m_data_total++;
if(pos<m_data_total-1)
{
if(MemMove(pos+1,pos,m_data_total-pos-1)<0)
return(false);
m_data[pos]=element;
}
else
m_data[m_data_total-1]=element;
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Inserting elements in the specified position |
//+------------------------------------------------------------------+
bool CArrayShort::InsertArray(const short &src[],const int pos)
{
int num=ArraySize(src);
//--- check/reserve elements of array
if(!Reserve(num))
return(false);
//--- insert
if(MemMove(num+pos,pos,m_data_total-pos)<0)
return(false);
for(int i=0;i<num;i++)
m_data[i+pos]=src[i];
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Inserting elements in the specified position |
//+------------------------------------------------------------------+
bool CArrayShort::InsertArray(const CArrayShort *src,const int pos)
{
int num;
//--- check
if(!CheckPointer(src))
return(false);
//--- check/reserve elements of array
num=src.Total();
if(!Reserve(num))
return(false);
//--- insert
if(MemMove(num+pos,pos,m_data_total-pos)<0)
return(false);
for(int i=0;i<num;i++)
m_data[i+pos]=src.m_data[i];
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Assignment (copying) of another array |
//+------------------------------------------------------------------+
bool CArrayShort::AssignArray(const short &src[])
{
int num=ArraySize(src);
//--- check/reserve elements of array
Clear();
if(m_data_max<num)
{
if(!Reserve(num))
return(false);
}
else
Resize(num);
//--- copy array
for(int i=0;i<num;i++)
{
m_data[i]=src[i];
m_data_total++;
}
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Assignment (copying) of another array |
//+------------------------------------------------------------------+
bool CArrayShort::AssignArray(const CArrayShort *src)
{
int num;
//--- check
if(!CheckPointer(src))
return(false);
//--- check/reserve elements of array
num=src.m_data_total;
Clear();
if(m_data_max<num)
{
if(!Reserve(num))
return(false);
}
else
Resize(num);
//--- copy array
for(int i=0;i<num;i++)
{
m_data[i]=src.m_data[i];
m_data_total++;
}
m_sort_mode=src.SortMode();
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Access to data in the specified position |
//+------------------------------------------------------------------+
short CArrayShort::At(const int index) const
{
//--- check
if(index<0 || index>=m_data_total)
return(SHORT_MAX);
//--- result
return(m_data[index]);
}
//+------------------------------------------------------------------+
//| Updating element in the specified position |
//+------------------------------------------------------------------+
bool CArrayShort::Update(const int index,const short element)
{
//--- check
if(index<0 || index>=m_data_total)
return(false);
//--- update
m_data[index]=element;
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Moving element from the specified position |
//| on the specified shift |
//+------------------------------------------------------------------+
bool CArrayShort::Shift(const int index,const int shift)
{
short tmp_short;
//--- check
if(index<0 || index+shift<0 || index+shift>=m_data_total)
return(false);
if(shift==0)
return(true);
//--- move
tmp_short=m_data[index];
if(shift>0)
{
if(MemMove(index,index+1,shift)<0)
return(false);
}
else
{
if(MemMove(index+shift+1,index+shift,-shift)<0)
return(false);
}
m_data[index+shift]=tmp_short;
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Deleting element from the specified position |
//+------------------------------------------------------------------+
bool CArrayShort::Delete(const int index)
{
//--- check
if(index<0 || index>=m_data_total)
return(false);
//--- delete
if(index<m_data_total-1 && MemMove(index,index+1,m_data_total-index-1)<0)
return(false);
m_data_total--;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Deleting range of elements |
//+------------------------------------------------------------------+
bool CArrayShort::DeleteRange(int from,int to)
{
//--- check
if(from<0 || to<0)
return(false);
if(from>to || from>=m_data_total)
return(false);
//--- delete
if(to>=m_data_total-1)
to=m_data_total-1;
if(MemMove(from,to+1,m_data_total-to-1)<0)
return(false);
m_data_total-=to-from+1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Equality comparison of two arrays |
//+------------------------------------------------------------------+
bool CArrayShort::CompareArray(const short &array[]) const
{
//--- compare
if(m_data_total!=ArraySize(array))
return(false);
for(int i=0;i<m_data_total;i++)
if(m_data[i]!=array[i])
return(false);
//--- equal
return(true);
}
//+------------------------------------------------------------------+
//| Equality comparison of two arrays |
//+------------------------------------------------------------------+
bool CArrayShort::CompareArray(const CArrayShort *array) const
{
//--- check
if(!CheckPointer(array))
return(false);
//--- compare
if(m_data_total!=array.m_data_total)
return(false);
for(int i=0;i<m_data_total;i++)
if(m_data[i]!=array.m_data[i])
return(false);
//--- equal
return(true);
}
//+------------------------------------------------------------------+
//| Method QuickSort |
//+------------------------------------------------------------------+
void CArrayShort::QuickSort(int beg,int end,const int mode)
{
int i,j;
short p_short,t_short;
//--- check
if(beg<0 || end<0)
return;
//--- sort
i=beg;
j=end;
while(i<end)
{
//--- ">>1" is quick division by 2
p_short=m_data[(beg+end)>>1];
while(i<j)
{
while(m_data[i]<p_short)
{
//--- control the output of the array bounds
if(i==m_data_total-1)
break;
i++;
}
while(m_data[j]>p_short)
{
//--- control the output of the array bounds
if(j==0)
break;
j--;
}
if(i<=j)
{
t_short=m_data[i];
m_data[i++]=m_data[j];
m_data[j]=t_short;
//--- control the output of the array bounds
if(j==0)
break;
j--;
}
}
if(beg<j)
QuickSort(beg,j);
beg=i;
j=end;
}
}
//+------------------------------------------------------------------+
//| Inserting element in a sorted array |
//+------------------------------------------------------------------+
bool CArrayShort::InsertSort(const short element)
{
int pos;
//--- check
if(!IsSorted())
return(false);
//--- check/reserve elements of array
if(!Reserve(1))
return(false);
//--- if the array is empty, add an element
if(m_data_total==0)
{
m_data[m_data_total++]=element;
return(true);
}
//--- find position and insert
pos=QuickSearch(element);
if(m_data[pos]>element)
Insert(element,pos);
else
Insert(element,pos+1);
//--- restore the sorting flag after Insert(...)
m_sort_mode=0;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Search of position of element in a array |
//+------------------------------------------------------------------+
int CArrayShort::SearchLinear(const short element) const
{
//--- check
if(m_data_total==0)
return(-1);
//---
for(int i=0;i<m_data_total;i++)
if(m_data[i]==element)
return(i);
//--- not found
return(-1);
}
//+------------------------------------------------------------------+
//| Quick search of position of element in a sorted array |
//+------------------------------------------------------------------+
int CArrayShort::QuickSearch(const short element) const
{
int i,j,m=-1;
short t_short;
//--- search
i=0;
j=m_data_total-1;
while(j>=i)
{
//--- ">>1" is quick division by 2
m=(j+i)>>1;
if(m<0 || m>=m_data_total)
break;
t_short=m_data[m];
if(t_short==element)
break;
if(t_short>element)
j=m-1;
else
i=m+1;
}
//--- position
return(m);
}
//+------------------------------------------------------------------+
//| Search of position of element in a sorted array |
//+------------------------------------------------------------------+
int CArrayShort::Search(const short element) const
{
int pos;
//--- check
if(m_data_total==0 || !IsSorted())
return(-1);
//--- search
pos=QuickSearch(element);
if(m_data[pos]==element)
return(pos);
//--- not found
return(-1);
}
//+------------------------------------------------------------------+
//| Search position of the first element which is greater than |
//| specified in a sorted array |
//+------------------------------------------------------------------+
int CArrayShort::SearchGreat(const short element) const
{
int pos;
//--- check
if(m_data_total==0 || !IsSorted())
return(-1);
//--- search
pos=QuickSearch(element);
while(m_data[pos]<=element)
if(++pos==m_data_total)
return(-1);
//--- position
return(pos);
}
//+------------------------------------------------------------------+
//| Search position of the first element which is less than |
//| specified in the sorted array |
//+------------------------------------------------------------------+
int CArrayShort::SearchLess(const short element) const
{
int pos;
//--- check
if(m_data_total==0 || !IsSorted())
return(-1);
//--- search
pos=QuickSearch(element);
while(m_data[pos]>=element)
if(pos--==0)
return(-1);
//--- position
return(pos);
}
//+------------------------------------------------------------------+
//| Search position of the first element which is greater than or |
//| equal to the specified in a sorted array |
//+------------------------------------------------------------------+
int CArrayShort::SearchGreatOrEqual(const short element) const
{
//--- check
if(m_data_total==0 || !IsSorted())
return(-1);
//--- search
for(int pos=QuickSearch(element);pos<m_data_total;pos++)
if(m_data[pos]>=element)
return(pos);
//--- not found
return(-1);
}
//+------------------------------------------------------------------+
//| Search position of the first element which is less than or equal |
//| to the specified in a sorted array |
//+------------------------------------------------------------------+
int CArrayShort::SearchLessOrEqual(const short element) const
{
//--- check
if(m_data_total==0 || !IsSorted())
return(-1);
//--- search
for(int pos=QuickSearch(element);pos>=0;pos--)
if(m_data[pos]<=element)
return(pos);
//--- not found
return(-1);
}
//+------------------------------------------------------------------+
//| Find position of first appearance of element in a sorted array |
//+------------------------------------------------------------------+
int CArrayShort::SearchFirst(const short element) const
{
int pos;
//--- check
if(m_data_total==0 || !IsSorted())
return(-1);
//--- search
pos=QuickSearch(element);
if(m_data[pos]==element)
{
while(m_data[pos]==element)
if(pos--==0)
break;
return(pos+1);
}
//--- not found
return(-1);
}
//+------------------------------------------------------------------+
//| Find position of last appearance of element in a sorted array |
//+------------------------------------------------------------------+
int CArrayShort::SearchLast(const short element) const
{
int pos;
//--- check
if(m_data_total==0 || !IsSorted())
return(-1);
//--- search
pos=QuickSearch(element);
if(m_data[pos]==element)
{
while(m_data[pos]==element)
if(++pos==m_data_total)
break;
return(pos-1);
}
//--- not found
return(-1);
}
//+------------------------------------------------------------------+
//| Writing array to file |
//+------------------------------------------------------------------+
bool CArrayShort::Save(const int file_handle)
{
int i=0;
//--- check
if(!CArray::Save(file_handle))
return(false);
//--- write array length
if(FileWriteInteger(file_handle,m_data_total,INT_VALUE)!=INT_VALUE)
return(false);
//--- write array
for(i=0;i<m_data_total;i++)
if(FileWriteInteger(file_handle,m_data[i],SHORT_VALUE)!=SHORT_VALUE)
break;
//--- result
return(i==m_data_total);
}
//+------------------------------------------------------------------+
//| Reading array from file |
//+------------------------------------------------------------------+
bool CArrayShort::Load(const int file_handle)
{
int i=0,num;
//--- check
if(!CArray::Load(file_handle))
return(false);
//--- read array length
num=FileReadInteger(file_handle,INT_VALUE);
//--- read array
Clear();
if(num!=0)
{
if(!Reserve(num))
return(false);
for(i=0;i<num;i++)
{
m_data[i]=(short)FileReadInteger(file_handle,SHORT_VALUE);
m_data_total++;
if(FileIsEnding(file_handle))
break;
}
}
m_sort_mode=-1;
//--- result
return(m_data_total==num);
}
//+------------------------------------------------------------------+
+780
View File
@@ -0,0 +1,780 @@
//+------------------------------------------------------------------+
//| ArrayString.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include "Array.mqh"
//+------------------------------------------------------------------+
//| Class CArrayString. |
//| Purpose: Class of dynamic array of variables of string type. |
//| Derives from class CArray. |
//+------------------------------------------------------------------+
class CArrayString : public CArray
{
protected:
string m_data[]; // data array
public:
CArrayString(void);
~CArrayString(void);
//--- method of identifying the object
virtual int Type(void) const { return(TYPE_STRING); }
//--- methods for working with files
virtual bool Save(const int file_handle);
virtual bool Load(const int file_handle);
//--- methods of managing dynamic memory
bool Reserve(const int size);
bool Resize(const int size);
bool Shutdown(void);
//--- methods of filling the array
bool Add(const string element);
bool AddArray(const string &src[]);
bool AddArray(const CArrayString *src);
bool Insert(const string element,const int pos);
bool InsertArray(const string &src[],const int pos);
bool InsertArray(const CArrayString *src,const int pos);
bool AssignArray(const string &src[]);
bool AssignArray(const CArrayString *src);
//--- method of access to the array
string At(const int index) const;
string operator[](const int index) const { return(At(index)); }
//--- methods of changing
bool Update(const int index,const string element);
bool Shift(const int index,const int shift);
//--- methods of deleting
bool Delete(const int index);
bool DeleteRange(int from,int to);
//--- methods for comparing arrays
bool CompareArray(const string &array[]) const;
bool CompareArray(const CArrayString *array) const;
//--- methods for working with the sorted array
bool InsertSort(const string element);
int Search(const string element) const;
int SearchGreat(const string element) const;
int SearchLess(const string element) const;
int SearchGreatOrEqual(const string element) const;
int SearchLessOrEqual(const string element) const;
int SearchFirst(const string element) const;
int SearchLast(const string element) const;
int SearchLinear(const string element) const;
protected:
virtual void QuickSort(int beg,int end,const int mode=0);
int QuickSearch(const string element) const;
int MemMove(const int dest,const int src,int count);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CArrayString::CArrayString(void)
{
//--- initialize protected data
m_data_max=ArraySize(m_data);
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CArrayString::~CArrayString(void)
{
if(m_data_max!=0)
Shutdown();
}
//+------------------------------------------------------------------+
//| Moving the memory within a single array |
//+------------------------------------------------------------------+
int CArrayString::MemMove(const int dest,const int src,int count)
{
int i;
//--- check parameters
if(dest<0 || src<0 || count<0)
return(-1);
//--- check count
if(src+count>m_data_total)
count=m_data_total-src;
if(count<0)
return(-1);
//--- no need to copy
if(dest==src || count==0)
return(dest);
//--- check data total
if(dest+count>m_data_total)
{
if(m_data_max<dest+count)
return(-1);
m_data_total=dest+count;
}
//--- copy
if(dest<src)
{
//--- copy from left to right
for(i=0;i<count;i++)
m_data[dest+i]=m_data[src+i];
}
else
{
//--- copy from right to left
for(i=count-1;i>=0;i--)
m_data[dest+i]=m_data[src+i];
}
//--- successful
return(dest);
}
//+------------------------------------------------------------------+
//| Request for more memory in an array. Checks if the requested |
//| number of free elements already exists; allocates additional |
//| memory with a given step |
//+------------------------------------------------------------------+
bool CArrayString::Reserve(const int size)
{
int new_size;
//--- check
if(size<=0)
return(false);
//--- resize array
if(Available()<size)
{
new_size=m_data_max+m_step_resize*(1+(size-Available())/m_step_resize);
if(new_size<0)
//--- overflow occurred when calculating new_size
return(false);
if((m_data_max=ArrayResize(m_data,new_size))==-1)
m_data_max=ArraySize(m_data);
}
//--- result
return(Available()>=size);
}
//+------------------------------------------------------------------+
//| Resizing (with removal of elements on the right) |
//+------------------------------------------------------------------+
bool CArrayString::Resize(const int size)
{
int new_size;
//--- check
if(size<0)
return(false);
//--- resize array
new_size=m_step_resize*(1+size/m_step_resize);
if(m_data_max!=new_size)
{
if((m_data_max=ArrayResize(m_data,new_size))==-1)
{
m_data_max=ArraySize(m_data);
return(false);
}
}
if(m_data_total>size)
m_data_total=size;
//--- result
return(m_data_max==new_size);
}
//+------------------------------------------------------------------+
//| Complete cleaning of the array with the release of memory |
//+------------------------------------------------------------------+
bool CArrayString::Shutdown(void)
{
//--- check
if(m_data_max==0)
return(true);
//--- clean
if(ArrayResize(m_data,0)==-1)
return(false);
m_data_total=0;
m_data_max=0;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Adding an element to the end of the array |
//+------------------------------------------------------------------+
bool CArrayString::Add(const string element)
{
//--- check/reserve elements of array
if(!Reserve(1))
return(false);
//--- add
m_data[m_data_total++]=element;
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Adding an element to the end of the array from another array |
//+------------------------------------------------------------------+
bool CArrayString::AddArray(const string &src[])
{
int num=ArraySize(src);
//--- check/reserve elements of array
if(!Reserve(num))
return(false);
//--- add
for(int i=0;i<num;i++)
m_data[m_data_total++]=src[i];
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Adding an element to the end of the array from another array |
//+------------------------------------------------------------------+
bool CArrayString::AddArray(const CArrayString *src)
{
int num;
//--- check
if(!CheckPointer(src))
return(false);
//--- check/reserve elements of array
num=src.Total();
if(!Reserve(num))
return(false);
//--- add
for(int i=0;i<num;i++)
m_data[m_data_total++]=src.m_data[i];
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Inserting an element in the specified position |
//+------------------------------------------------------------------+
bool CArrayString::Insert(const string element,const int pos)
{
//--- check/reserve elements of array
if(pos<0 || !Reserve(1))
return(false);
//--- insert
m_data_total++;
if(pos<m_data_total-1)
{
if(MemMove(pos+1,pos,m_data_total-pos-1)<0)
return(false);
m_data[pos]=element;
}
else
m_data[m_data_total-1]=element;
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Inserting elements in the specified position |
//+------------------------------------------------------------------+
bool CArrayString::InsertArray(const string &src[],const int pos)
{
int num=ArraySize(src);
//--- check/reserve elements of array
if(!Reserve(num))
return(false);
//--- insert
if(MemMove(num+pos,pos,m_data_total-pos)<0)
return(false);
for(int i=0;i<num;i++)
m_data[i+pos]=src[i];
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Inserting elements in the specified position |
//+------------------------------------------------------------------+
bool CArrayString::InsertArray(const CArrayString *src,const int pos)
{
int num;
//--- check
if(!CheckPointer(src))
return(false);
//--- check/reserve elements of array
num=src.Total();
if(!Reserve(num))
return(false);
//--- insert
if(MemMove(num+pos,pos,m_data_total-pos)<0)
return(false);
for(int i=0;i<num;i++)
m_data[i+pos]=src.m_data[i];
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Assignment (copying) of another array |
//+------------------------------------------------------------------+
bool CArrayString::AssignArray(const string &src[])
{
int num=ArraySize(src);
//--- check/reserve elements of array
Clear();
if(m_data_max<num)
{
if(!Reserve(num))
return(false);
}
else
Resize(num);
//--- copy array
for(int i=0;i<num;i++)
{
m_data[i]=src[i];
m_data_total++;
}
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Assignment (copying) of another array |
//+------------------------------------------------------------------+
bool CArrayString::AssignArray(const CArrayString *src)
{
int num;
//--- check
if(!CheckPointer(src))
return(false);
//--- check/reserve elements of array
num=src.m_data_total;
Clear();
if(m_data_max<num)
{
if(!Reserve(num))
return(false);
}
else
Resize(num);
//--- copy array
for(int i=0;i<num;i++)
{
m_data[i]=src.m_data[i];
m_data_total++;
}
m_sort_mode=src.SortMode();
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Access to data in the specified position |
//+------------------------------------------------------------------+
string CArrayString::At(const int index) const
{
//--- check
if(index<0 || index>=m_data_total)
return("");
//--- result
return(m_data[index]);
}
//+------------------------------------------------------------------+
//| Updating element in the specified position |
//+------------------------------------------------------------------+
bool CArrayString::Update(const int index,const string element)
{
//--- check
if(index<0 || index>=m_data_total)
return(false);
//--- update
m_data[index]=element;
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Moving element from the specified position |
//| on the specified shift |
//+------------------------------------------------------------------+
bool CArrayString::Shift(const int index,const int shift)
{
string tmp_string;
//--- check
if(index<0 || index+shift<0 || index+shift>=m_data_total)
return(false);
if(shift==0)
return(true);
//--- move
tmp_string=m_data[index];
if(shift>0)
{
if(MemMove(index,index+1,shift)<0)
return(false);
}
else
{
if(MemMove(index+shift+1,index+shift,-shift)<0)
return(false);
}
m_data[index+shift]=tmp_string;
m_sort_mode=-1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Deleting element from the specified position |
//+------------------------------------------------------------------+
bool CArrayString::Delete(const int index)
{
//--- check
if(index<0 || index>=m_data_total)
return(false);
//--- delete
if(index<m_data_total-1 && MemMove(index,index+1,m_data_total-index-1)<0)
return(false);
m_data_total--;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Deleting range of elements |
//+------------------------------------------------------------------+
bool CArrayString::DeleteRange(int from,int to)
{
//--- check
if(from<0 || to<0)
return(false);
if(from>to || from>=m_data_total)
return(false);
//--- delete
if(to>=m_data_total-1)
to=m_data_total-1;
if(MemMove(from,to+1,m_data_total-to-1)<0)
return(false);
m_data_total-=to-from+1;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Equality comparison of two arrays |
//+------------------------------------------------------------------+
bool CArrayString::CompareArray(const string &array[]) const
{
//--- compare
if(m_data_total!=ArraySize(array))
return(false);
for(int i=0;i<m_data_total;i++)
if(m_data[i]!=array[i])
return(false);
//--- equal
return(true);
}
//+------------------------------------------------------------------+
//| Equality comparison of two arrays |
//+------------------------------------------------------------------+
bool CArrayString::CompareArray(const CArrayString *array) const
{
//--- check
if(!CheckPointer(array))
return(false);
//--- compare
if(m_data_total!=array.m_data_total)
return(false);
for(int i=0;i<m_data_total;i++)
if(m_data[i]!=array.m_data[i])
return(false);
//--- equal
return(true);
}
//+------------------------------------------------------------------+
//| Method QuickSort |
//+------------------------------------------------------------------+
void CArrayString::QuickSort(int beg,int end,const int mode)
{
int i,j;
string p_string;
string t_string;
//--- check
if(beg<0 || end<0)
return;
//--- sort
i=beg;
j=end;
while(i<end)
{
//--- ">>1" is quick division by 2
p_string=m_data[(beg+end)>>1];
while(i<j)
{
while(m_data[i]<p_string)
{
//--- control the output of the array bounds
if(i==m_data_total-1)
break;
i++;
}
while(m_data[j]>p_string)
{
//--- control the output of the array bounds
if(j==0)
break;
j--;
}
if(i<=j)
{
t_string=m_data[i];
m_data[i++]=m_data[j];
m_data[j]=t_string;
//--- control the output of the array bounds
if(j==0)
break;
j--;
}
}
if(beg<j)
QuickSort(beg,j);
beg=i;
j=end;
}
}
//+------------------------------------------------------------------+
//| Inserting element in a sorted array |
//+------------------------------------------------------------------+
bool CArrayString::InsertSort(const string element)
{
int pos;
//--- check
if(!IsSorted())
return(false);
//--- check/reserve elements of array
if(!Reserve(1))
return(false);
//--- if the array is empty, add an element
if(m_data_total==0)
{
m_data[m_data_total++]=element;
return(true);
}
//--- find position and insert
pos=QuickSearch(element);
if(m_data[pos]>element)
Insert(element,pos);
else
Insert(element,pos+1);
//--- restore the sorting flag after Insert(...)
m_sort_mode=0;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Search of position of element in a array |
//+------------------------------------------------------------------+
int CArrayString::SearchLinear(const string element) const
{
//--- check
if(m_data_total==0)
return(-1);
//---
for(int i=0;i<m_data_total;i++)
if(m_data[i]==element)
return(i);
//--- not found
return(-1);
}
//+------------------------------------------------------------------+
//| Quick search of position of element in a sorted array |
//+------------------------------------------------------------------+
int CArrayString::QuickSearch(const string element) const
{
int i,j,m=-1;
string t_string;
//--- search
i=0;
j=m_data_total-1;
while(j>=i)
{
//--- ">>1" is quick division by 2
m=(j+i)>>1;
if(m<0 || m>=m_data_total)
break;
t_string=m_data[m];
if(t_string==element)
break;
if(t_string>element)
j=m-1;
else
i=m+1;
}
//--- position
return(m);
}
//+------------------------------------------------------------------+
//| Search of position of element in a sorted array |
//+------------------------------------------------------------------+
int CArrayString::Search(const string element) const
{
int pos;
//--- check
if(m_data_total==0 || !IsSorted())
return(-1);
//--- search
pos=QuickSearch(element);
if(m_data[pos]==element)
return(pos);
//--- not found
return(-1);
}
//+------------------------------------------------------------------+
//| Search position of the first element which is greater than |
//| specified in a sorted array |
//+------------------------------------------------------------------+
int CArrayString::SearchGreat(const string element) const
{
int pos;
//--- check
if(m_data_total==0 || !IsSorted())
return(-1);
//--- search
pos=QuickSearch(element);
while(m_data[pos]<=element)
if(++pos==m_data_total)
return(-1);
//--- position
return(pos);
}
//+------------------------------------------------------------------+
//| Search position of the first element which is less than |
//| specified in the sorted array |
//+------------------------------------------------------------------+
int CArrayString::SearchLess(const string element) const
{
int pos;
//--- check
if(m_data_total==0 || !IsSorted())
return(-1);
//--- search
pos=QuickSearch(element);
while(m_data[pos]>=element)
if(pos--==0)
return(-1);
//--- position
return(pos);
}
//+------------------------------------------------------------------+
//| Search position of the first element which is greater than or |
//| equal to the specified in a sorted array |
//+------------------------------------------------------------------+
int CArrayString::SearchGreatOrEqual(const string element) const
{
//--- check
if(m_data_total==0 || !IsSorted())
return(-1);
//--- search
for(int pos=QuickSearch(element);pos<m_data_total;pos++)
if(m_data[pos]>=element)
return(pos);
//--- not found
return(-1);
}
//+------------------------------------------------------------------+
//| Search position of the first element which is less than or equal |
//| to the specified in a sorted array |
//+------------------------------------------------------------------+
int CArrayString::SearchLessOrEqual(const string element) const
{
//--- check
if(m_data_total==0 || !IsSorted())
return(-1);
//--- search
for(int pos=QuickSearch(element);pos>=0;pos--)
if(m_data[pos]<=element)
return(pos);
//--- not found
return(-1);
}
//+------------------------------------------------------------------+
//| Find position of first appearance of element in a sorted array |
//+------------------------------------------------------------------+
int CArrayString::SearchFirst(const string element) const
{
int pos;
//--- check
if(m_data_total==0 || !IsSorted())
return(-1);
//--- search
pos=QuickSearch(element);
if(m_data[pos]==element)
{
while(m_data[pos]==element)
if(pos--==0)
break;
return(pos+1);
}
//--- not found
return(-1);
}
//+------------------------------------------------------------------+
//| Find position of last appearance of element in a sorted array |
//+------------------------------------------------------------------+
int CArrayString::SearchLast(const string element) const
{
int pos;
//--- check
if(m_data_total==0 || !IsSorted())
return(-1);
//--- search
pos=QuickSearch(element);
if(m_data[pos]==element)
{
while(m_data[pos]==element)
if(++pos==m_data_total)
break;
return(pos-1);
}
//--- not found
return(-1);
}
//+------------------------------------------------------------------+
//| Writing array to file |
//+------------------------------------------------------------------+
bool CArrayString::Save(const int file_handle)
{
int i=0,len;
//--- check
if(!CArray::Save(file_handle))
return(false);
//--- write array length
if(FileWriteInteger(file_handle,m_data_total,INT_VALUE)!=INT_VALUE)
return(false);
//--- write array
for(i=0;i<m_data_total;i++)
{
len=StringLen(m_data[i]);
//--- write string length
if(FileWriteInteger(file_handle,len,INT_VALUE)!=INT_VALUE)
return(false);
//--- write string
if(len!=0) if(FileWriteString(file_handle,m_data[i],len)!=len)
break;
}
//--- result
return(i==m_data_total);
}
//+------------------------------------------------------------------+
//| Reading array from file |
//+------------------------------------------------------------------+
bool CArrayString::Load(const int file_handle)
{
int i=0,num,len;
//--- check
if(!CArray::Load(file_handle))
return(false);
//--- read array length
num=FileReadInteger(file_handle,INT_VALUE);
//--- read array
Clear();
if(num!=0)
{
if(!Reserve(num))
return(false);
for(i=0;i<num;i++)
{
//--- read string length
len=FileReadInteger(file_handle,INT_VALUE);
//--- read string
if(len!=0)
m_data[i]=FileReadString(file_handle,len);
else
m_data[i]="";
m_data_total++;
if(FileIsEnding(file_handle))
break;
}
}
m_sort_mode=-1;
//--- result
return(m_data_total==num);
}
//+------------------------------------------------------------------+
+657
View File
@@ -0,0 +1,657 @@
//+------------------------------------------------------------------+
//| List.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Object.mqh>
//+------------------------------------------------------------------+
//| Class CList. |
//| Purpose: Provides the possibility of working with the list of |
//| CObject instances and its dervivatives |
//| Derives from class CObject. |
//+------------------------------------------------------------------+
class CList : public CObject
{
protected:
CObject *m_first_node; // pointer to the first element of the list
CObject *m_last_node; // pointer to the last element of the list
CObject *m_curr_node; // pointer to the current element of the list
int m_curr_idx; // index of the current list item
int m_data_total; // number of elements
bool m_free_mode; // flag of the necessity of "physical" deletion of object
bool m_data_sort; // flag if the list is sorted or not
int m_sort_mode; // mode of sorting of array
public:
CList(void);
~CList(void);
//--- methods of access to protected data
bool FreeMode(void) const { return(m_free_mode); }
void FreeMode(bool mode) { m_free_mode=mode; }
int Total(void) const { return(m_data_total); }
bool IsSorted(void) const { return(m_data_sort); }
int SortMode(void) const { return(m_sort_mode); }
//--- method of identifying the object
virtual int Type(void) const { return(0x7779); }
//--- methods for working with files
virtual bool Save(const int file_handle);
virtual bool Load(const int file_handle);
//--- method of creating an element of the list
virtual CObject *CreateElement(void) { return(NULL); }
//--- methods of filling the list
int Add(CObject *new_node);
int Insert(CObject *new_node,int index);
//--- methods for navigating
int IndexOf(CObject *node);
CObject *GetNodeAtIndex(int index);
CObject *GetFirstNode(void);
CObject *GetPrevNode(void);
CObject *GetCurrentNode(void);
CObject *GetNextNode(void);
CObject *GetLastNode(void);
//--- methods for deleting
CObject *DetachCurrent(void);
bool DeleteCurrent(void);
bool Delete(int index);
void Clear(void);
//--- method for comparing lists
bool CompareList(CList *List);
//--- methods for changing
void Sort(int mode);
bool MoveToIndex(int index);
bool Exchange(CObject *node1,CObject *node2);
//--- method for searching
CObject *Search(CObject *element);
protected:
void QuickSort(int beg,int end,int mode);
CObject *QuickSearch(CObject *element);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CList::CList(void) : m_first_node(NULL),
m_last_node(NULL),
m_curr_node(NULL),
m_curr_idx(-1),
m_data_total(0),
m_free_mode(true),
m_data_sort(false),
m_sort_mode(0)
{
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CList::~CList(void)
{
Clear();
}
//+------------------------------------------------------------------+
//| Method QuickSort |
//+------------------------------------------------------------------+
void CList::QuickSort(int beg,int end,int mode)
{
int i,j,k;
CObject *i_ptr,*j_ptr,*k_ptr;
//---
i_ptr=GetNodeAtIndex(i=beg);
j_ptr=GetNodeAtIndex(j=end);
while(i<end)
{
//--- ">>1" is quick division by 2
k_ptr=GetNodeAtIndex(k=(beg+end)>>1);
while(i<j)
{
while(i_ptr.Compare(k_ptr,mode)<0)
{
//--- control the output of the array bounds
if(i==m_data_total-1)
break;
i++;
i_ptr=i_ptr.Next();
}
while(j_ptr.Compare(k_ptr,mode)>0)
{
//--- control the output of the array bounds
if(j==0)
break;
j--;
j_ptr=j_ptr.Prev();
}
if(i<=j)
{
Exchange(i_ptr,j_ptr);
i++;
i_ptr=GetNodeAtIndex(i);
//--- control the output of the array bounds
if(j==0)
break;
else
{
j--;
j_ptr=GetNodeAtIndex(j);
}
}
}
if(beg<j)
QuickSort(beg,j,mode);
beg=i;
i_ptr=GetNodeAtIndex(i=beg);
j_ptr=GetNodeAtIndex(j=end);
}
}
//+------------------------------------------------------------------+
//| Index of element specified via the pointer to the list item |
//+------------------------------------------------------------------+
int CList::IndexOf(CObject *node)
{
//--- check
if(!CheckPointer(node) || !CheckPointer(m_curr_node))
return(-1);
//--- searching index
if(node==m_curr_node)
return(m_curr_idx);
if(GetFirstNode()==node)
return(0);
for(int i=1;i<m_data_total;i++)
if(GetNextNode()==node)
return(i);
//---
return(-1);
}
//+------------------------------------------------------------------+
//| Adding a new element to the end of the list |
//+------------------------------------------------------------------+
int CList::Add(CObject *new_node)
{
//--- check
if(!CheckPointer(new_node))
return(-1);
//--- add
if(m_first_node==NULL)
m_first_node=new_node;
else
{
m_last_node.Next(new_node);
new_node.Prev(m_last_node);
}
m_curr_node=new_node;
m_curr_idx=m_data_total;
m_last_node=new_node;
m_data_sort=false;
//--- result
return(m_data_total++);
}
//+------------------------------------------------------------------+
//| Inserting a new element to the specified position in the list. |
//| Inserting element to the current position of the list if index=-1|
//+------------------------------------------------------------------+
int CList::Insert(CObject *new_node,int index)
{
CObject *tmp_node;
//--- check
if(!CheckPointer(new_node))
return(-1);
if(index>m_data_total || index<0)
return(-1);
//--- adjust
if(index==-1)
{
if(m_curr_node==NULL)
return(Add(new_node));
}
else
{
if(GetNodeAtIndex(index)==NULL)
return(Add(new_node));
}
//--- no need to check m_curr_node
tmp_node=m_curr_node.Prev();
new_node.Prev(tmp_node);
if(tmp_node!=NULL)
tmp_node.Next(new_node);
else
m_first_node=new_node;
new_node.Next(m_curr_node);
m_curr_node.Prev(new_node);
m_data_total++;
m_data_sort=false;
m_curr_node=new_node;
//--- result
return(index);
}
//+------------------------------------------------------------------+
//| Get a pointer to the position of element in the list |
//+------------------------------------------------------------------+
CObject *CList::GetNodeAtIndex(int index)
{
int i;
bool revers;
CObject *result;
//--- check
if(index>=m_data_total)
return(NULL);
if(index==m_curr_idx)
return(m_curr_node);
//--- optimize bust list
if(index<m_curr_idx)
{
//--- index to the left of the current
if(m_curr_idx-index<index)
{
//--- closer to the current index
i=m_curr_idx;
revers=true;
result=m_curr_node;
}
else
{
//--- closer to the top of the list
i=0;
revers=false;
result=m_first_node;
}
}
else
{
//--- index to the right of the current
if(index-m_curr_idx<m_data_total-index-1)
{
//--- closer to the current index
i=m_curr_idx;
revers=false;
result=m_curr_node;
}
else
{
//--- closer to the end of the list
i=m_data_total-1;
revers=true;
result=m_last_node;
}
}
if(!CheckPointer(result))
return(NULL);
//---
if(revers)
{
//--- search from right to left
for(;i>index;i--)
{
result=result.Prev();
if(result==NULL)
return(NULL);
}
}
else
{
//--- search from left to right
for(;i<index;i++)
{
result=result.Next();
if(result==NULL)
return(NULL);
}
}
m_curr_idx=index;
//--- result
return(m_curr_node=result);
}
//+------------------------------------------------------------------+
//| Get a pointer to the first itme of the list |
//+------------------------------------------------------------------+
CObject *CList::GetFirstNode(void)
{
//--- check
if(!CheckPointer(m_first_node))
return(NULL);
//--- save
m_curr_idx=0;
//--- result
return(m_curr_node=m_first_node);
}
//+------------------------------------------------------------------+
//| Get a pointer to the previous itme of the list |
//+------------------------------------------------------------------+
CObject *CList::GetPrevNode(void)
{
//--- check
if(!CheckPointer(m_curr_node) || m_curr_node.Prev()==NULL)
return(NULL);
//--- decrement
m_curr_idx--;
//--- result
return(m_curr_node=m_curr_node.Prev());
}
//+------------------------------------------------------------------+
//| Get a pointer to the current item of the list |
//+------------------------------------------------------------------+
CObject *CList::GetCurrentNode(void)
{
return(m_curr_node);
}
//+------------------------------------------------------------------+
//| Get a pointer to the next item of the list |
//+------------------------------------------------------------------+
CObject *CList::GetNextNode(void)
{
//--- check
if(!CheckPointer(m_curr_node) || m_curr_node.Next()==NULL)
return(NULL);
//--- increment
m_curr_idx++;
//--- result
return(m_curr_node=m_curr_node.Next());
}
//+------------------------------------------------------------------+
//| Get a pointer to the last itme of the list |
//+------------------------------------------------------------------+
CObject *CList::GetLastNode(void)
{
//--- check
if(!CheckPointer(m_last_node))
return(NULL);
//---
m_curr_idx=m_data_total-1;
//--- result
return(m_curr_node=m_last_node);
}
//+------------------------------------------------------------------+
//| Detach current item in the list |
//+------------------------------------------------------------------+
CObject *CList::DetachCurrent(void)
{
CObject *tmp_node,*result=NULL;
//--- check
if(!CheckPointer(m_curr_node))
return(result);
//--- "explode" list
result=m_curr_node;
m_curr_node=NULL;
//--- if the deleted item was not the last one, pull up the "tail" of the list
if((tmp_node=result.Next())!=NULL)
{
tmp_node.Prev(result.Prev());
m_curr_node=tmp_node;
}
//--- if the deleted item was not the first one, pull up "head" list
if((tmp_node=result.Prev())!=NULL)
{
tmp_node.Next(result.Next());
//--- if "last_node" is removed, move the current pointer to the end of the list
if(m_curr_node==NULL)
{
m_curr_node=tmp_node;
m_curr_idx=m_data_total-2;
}
}
m_data_total--;
//--- if necessary, adjust the settings of the first and last elements
if(m_first_node==result)
m_first_node=result.Next();
if(m_last_node==result)
m_last_node=result.Prev();
//--- complete the processing of element removed from the list
//--- remove references to the list
result.Prev(NULL);
result.Next(NULL);
//--- result
return(result);
}
//+------------------------------------------------------------------+
//| Delete current item of list item |
//+------------------------------------------------------------------+
bool CList::DeleteCurrent(void)
{
CObject *result=DetachCurrent();
//--- check
if(result==NULL)
return(false);
//--- complete the processing of element removed from the list
if(m_free_mode)
{
//--- delete it "physically"
if(CheckPointer(result)==POINTER_DYNAMIC)
delete result;
}
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Delete an item from a given position in the list |
//+------------------------------------------------------------------+
bool CList::Delete(int index)
{
if(GetNodeAtIndex(index)==NULL)
return(false);
//--- result
return(DeleteCurrent());
}
//+------------------------------------------------------------------+
//| Remove all items from the list |
//+------------------------------------------------------------------+
void CList::Clear(void)
{
GetFirstNode();
while(m_data_total!=0)
if(!DeleteCurrent())
break;
}
//+------------------------------------------------------------------+
//| Equality comparing of two lists |
//+------------------------------------------------------------------+
bool CList::CompareList(CList *List)
{
CObject *node,*lnode;
//--- check
if(!CheckPointer(List))
return(false);
if((node=GetFirstNode())==NULL)
return(false);
if((lnode=List.GetFirstNode())==NULL)
return(false);
//--- compare
if(node.Compare(lnode)!=0)
return(false);
while((node=GetNextNode())!=NULL)
{
if((lnode=List.GetNextNode())==NULL)
return(false);
if(node.Compare(lnode)!=0)
return(false);
}
//--- equal
return(true);
}
//+------------------------------------------------------------------+
//| Sorting an array in ascending order |
//+------------------------------------------------------------------+
void CList::Sort(int mode)
{
//--- check
if(m_data_total==0)
return;
if(m_data_sort && m_sort_mode==mode)
return;
//--- sort
QuickSort(0,m_data_total-1,mode);
m_sort_mode=mode;
m_data_sort=true;
}
//+------------------------------------------------------------------+
//| Move the current item of list to the specified position |
//+------------------------------------------------------------------+
bool CList::MoveToIndex(int index)
{
//--- check
if(index>=m_data_total || !CheckPointer(m_curr_node))
return(false);
//--- tune
if(m_curr_idx==index)
return(true);
if(m_curr_idx<index)
index--;
//--- move
Insert(DetachCurrent(),index);
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Move an item of the list from the specified position to the |
//| current one |
//+------------------------------------------------------------------+
bool CList::Exchange(CObject *node1,CObject *node2)
{
CObject *tmp_node,*node;
//--- check
if(!CheckPointer(node1) || !CheckPointer(node2))
return(false);
//---
tmp_node=node1.Prev();
node1.Prev(node2.Prev());
if(node1.Prev()!=NULL)
{
node=node1.Prev();
node.Next(node1);
}
else
m_first_node=node1;
node2.Prev(tmp_node);
if(node2.Prev()!=NULL)
{
node=node2.Prev();
node.Next(node2);
}
else
m_first_node=node2;
tmp_node=node1.Next();
node1.Next(node2.Next());
if(node1.Next()!=NULL)
{
node=node1.Next();
node.Prev(node1);
}
else
m_last_node=node1;
node2.Next(tmp_node);
if(node2.Next()!=NULL)
{
node=node2.Next();
node.Prev(node2);
}
else
m_last_node=node2;
//---
m_curr_idx=0;
m_curr_node=m_first_node;
m_data_sort=false;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Search position of an element in a sorted list |
//+------------------------------------------------------------------+
CObject *CList::QuickSearch(CObject *element)
{
int i,j,m;
CObject *t_node=NULL;
//--- check
if(m_data_total==0)
return(NULL);
//--- check the pointer is not needed
i=0;
j=m_data_total;
while(j>=i)
{
//--- ">>1" is quick division by 2
m=(j+i)>>1;
if(m<0 || m>=m_data_total)
break;
t_node=GetNodeAtIndex(m);
if(t_node.Compare(element,m_sort_mode)==0)
break;
if(t_node.Compare(element,m_sort_mode)>0)
j=m-1;
else
i=m+1;
t_node=NULL;
}
//--- result
return(t_node);
}
//+------------------------------------------------------------------+
//| Search position of an element in a sorted list |
//+------------------------------------------------------------------+
CObject *CList::Search(CObject *element)
{
CObject *result;
//--- check
if(!CheckPointer(element) || !m_data_sort)
return(NULL);
//--- search
result=QuickSearch(element);
//--- result
return(result);
}
//+------------------------------------------------------------------+
//| Writing list to file |
//+------------------------------------------------------------------+
bool CList::Save(const int file_handle)
{
CObject *node;
bool result=true;
//--- check
if(!CheckPointer(m_curr_node) || file_handle==INVALID_HANDLE)
return(false);
//--- write start marker - 0xFFFFFFFFFFFFFFFF
if(FileWriteLong(file_handle,-1)!=sizeof(long))
return(false);
//--- write type
if(FileWriteInteger(file_handle,Type(),INT_VALUE)!=INT_VALUE)
return(false);
//--- write list size
if(FileWriteInteger(file_handle,m_data_total,INT_VALUE)!=INT_VALUE)
return(false);
//--- sequential scannning of elements in the list using the call of method Save()
node=m_first_node;
while(node!=NULL)
{
result&=node.Save(file_handle);
node=node.Next();
}
//--- successful
return(result);
}
//+------------------------------------------------------------------+
//| Reading list from file |
//+------------------------------------------------------------------+
bool CList::Load(const int file_handle)
{
uint i,num;
CObject *node;
bool result=true;
//--- check
if(file_handle==INVALID_HANDLE)
return(false);
//--- read and checking begin marker - 0xFFFFFFFFFFFFFFFF
if(FileReadLong(file_handle)!=-1)
return(false);
//--- read and checking type
if(FileReadInteger(file_handle,INT_VALUE)!=Type())
return(false);
//--- read list size
num=FileReadInteger(file_handle,INT_VALUE);
//--- sequential creation of list items using the call of method Load()
Clear();
for(i=0;i<num;i++)
{
node=CreateElement();
if(node==NULL)
return(false);
Add(node);
result&=node.Load(file_handle);
}
//--- successful
return(result);
}
//+------------------------------------------------------------------+
+415
View File
@@ -0,0 +1,415 @@
//+------------------------------------------------------------------+
//| Tree.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include "TreeNode.mqh"
//+------------------------------------------------------------------+
//| Class CTree. |
//| Purpose: Building a binary tree of instances of CTreeNode class |
//| and its derviatives. |
//| Derives from class CTreeNode. |
//+------------------------------------------------------------------+
class CTree : public CTreeNode
{
protected:
CTreeNode *m_root_node; // root node of the tree
public:
CTree(void);
~CTree(void);
//--- methods of access to protected data
CTreeNode *Root(void) const { return(m_root_node); }
//--- method of identifying the object
virtual int Type() const { return(0x9999); }
//--- method of filling the tree
CTreeNode *Insert(CTreeNode *new_node);
//--- methods of removing tree nodes
bool Detach(CTreeNode *node);
bool Delete(CTreeNode *node);
void Clear(void);
//--- method of searching data in the tree
CTreeNode *Find(const CTreeNode *node);
//--- method to create elements in the tree
virtual CTreeNode *CreateElement() { return(NULL); }
//--- methods for working with files
virtual bool Save(const int file_handle);
virtual bool Load(const int file_handle);
protected:
void Balance(CTreeNode *node);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CTree::CTree(void) : m_root_node(NULL)
{
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CTree::~CTree(void)
{
Clear();
}
//+------------------------------------------------------------------+
//| Method of adding a node to the tree |
//+------------------------------------------------------------------+
CTreeNode *CTree::Insert(CTreeNode *new_node)
{
CTreeNode *p_node;
CTreeNode *result=m_root_node;
//--- check
if(!CheckPointer(new_node))
return(NULL);
//--- add
if(result!=NULL)
{
p_node=NULL;
result=m_root_node;
while(result!=NULL && result.Compare(new_node)!=0)
{
p_node=result;
result=result.GetNext(new_node);
}
if(result!=NULL)
return(result);
if(p_node.Compare(new_node)>0)
p_node.Left(new_node);
else
p_node.Right(new_node);
new_node.Parent(p_node);
Balance(p_node);
}
else
m_root_node=new_node;
//--- result
return(result);
}
//+------------------------------------------------------------------+
//| Method of removing a node from the tree |
//+------------------------------------------------------------------+
bool CTree::Delete(CTreeNode *node)
{
//--- check
if(!CheckPointer(node))
return(false);
//--- delete
if(Detach(node) && CheckPointer(node)==POINTER_DYNAMIC)
delete node;
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Method of detaching node from the tree |
//+------------------------------------------------------------------+
bool CTree::Detach(CTreeNode *node)
{
CTreeNode *curr_node,*tmp_node;
CTreeNode *nodeA,*nodeB;
//--- check
curr_node=node;
if(!CheckPointer(curr_node))
return(false);
//--- detach
if(curr_node.BalanceL()>curr_node.BalanceR())
{
nodeA=curr_node.Left();
while(nodeA.Right()!=NULL)
nodeA=nodeA.Right();
nodeB=nodeA.Parent();
if(nodeB!=curr_node)
{
nodeB.Right(nodeA.Left());
tmp_node=nodeB.Right();
if(tmp_node!=NULL)
tmp_node.Parent(nodeB);
tmp_node=curr_node.Left();
nodeA.Left(tmp_node);
tmp_node.Parent(nodeA);
}
//--- left link of curr_node is already installed as it should be
curr_node.Left(NULL);
//--- transferring the right link of curr_node to nodeA
nodeA.Right(curr_node.Right());
tmp_node=curr_node.Right();
if(tmp_node!=NULL)
tmp_node.Parent(nodeA);
curr_node.Right(NULL);
//--- transferring the root link of curr_node to nodeA
tmp_node=curr_node.Parent();
nodeA.Parent(tmp_node);
if(tmp_node!=NULL)
{
if(tmp_node.Left()==curr_node)
tmp_node.Left(nodeA);
else
tmp_node.Right(nodeA);
}
else
{
curr_node.Parent(NULL);
m_root_node=nodeA;
tmp_node=nodeA;
}
Balance(tmp_node);
}
else
{
if(curr_node.BalanceR()>0)
{
nodeA=curr_node.Right();
while(nodeA.Left()!=NULL)
nodeA=nodeA.Left();
nodeB=nodeA.Parent();
if(nodeB!=curr_node)
{
nodeB.Left(nodeA.Right());
tmp_node=nodeB.Left();
if(tmp_node!=NULL)
tmp_node.Parent(nodeB);
tmp_node=curr_node.Right();
nodeA.Right(tmp_node);
tmp_node.Parent(nodeA);
}
//--- right link of curr_node is already installed as it should be
curr_node.Right(NULL);
//--- transferring the left link of curr_node to nodeA
nodeA.Left(curr_node.Left());
tmp_node=curr_node.Left();
if(tmp_node!=NULL)
tmp_node.Parent(nodeA);
curr_node.Left(NULL);
//--- transferring the root link of curr_node to nodeA
tmp_node=curr_node.Parent();
nodeA.Parent(tmp_node);
if(tmp_node!=NULL)
{
if(tmp_node.Left()==curr_node)
tmp_node.Left(nodeA);
else
tmp_node.Right(nodeA);
}
else
{
curr_node.Parent(NULL);
m_root_node=nodeA;
tmp_node=nodeA;
}
Balance(tmp_node);
}
else
{
//--- node list
if(curr_node.Parent()==NULL)
m_root_node=NULL;
else
{
tmp_node=curr_node.Parent();
if(tmp_node.Left()==curr_node)
tmp_node.Left(NULL);
else
tmp_node.Right(NULL);
curr_node.Parent(NULL);
}
Balance(curr_node.Parent());
}
}
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Method of cleaning the tree |
//+------------------------------------------------------------------+
void CTree::Clear(void)
{
if(CheckPointer(m_root_node)==POINTER_DYNAMIC)
delete m_root_node;
m_root_node=NULL;
}
//+------------------------------------------------------------------+
//| Method of searching for a node in the tree |
//+------------------------------------------------------------------+
CTreeNode *CTree::Find(const CTreeNode *node)
{
CTreeNode *result=m_root_node;
//--- find
while(result!=NULL && result.Compare(node)!=0)
result=result.GetNext(node);
//--- result
return(result);
}
//+------------------------------------------------------------------+
//| Method of balancing the tree |
//+------------------------------------------------------------------+
void CTree::Balance(CTreeNode *node)
{
CTreeNode *nodeA,*nodeB,*nodeC,*curr_node,*tmp_node;
//---
curr_node=node;
while(curr_node!=NULL)
{
curr_node.RefreshBalance();
if(MathAbs(curr_node.BalanceL()-curr_node.BalanceR())<=1)
curr_node=curr_node.Parent();
else
{
if(curr_node.BalanceR()>curr_node.BalanceL())
{
//--- rotation to the right
tmp_node=curr_node.Right();
if(tmp_node.BalanceL()>tmp_node.BalanceR())
{
//--- great rotation to the right
nodeA=curr_node;
nodeB=nodeA.Right();
nodeC=nodeB.Left();
nodeC.Parent(nodeA.Parent());
tmp_node=nodeC.Parent();
if(tmp_node!=NULL)
{
if(tmp_node.Right()==nodeA)
tmp_node.Right(nodeC);
else
tmp_node.Left(nodeC);
}
else
m_root_node=nodeC;
nodeA.Parent(nodeC);
nodeB.Parent(nodeC);
nodeA.Right(nodeC.Left());
tmp_node=nodeA.Right();
if(tmp_node!=NULL)
tmp_node.Parent(nodeA);
nodeC.Left(nodeA);
nodeB.Left(nodeC.Right());
tmp_node=nodeB.Left();
if(tmp_node!=NULL)
tmp_node.Parent(nodeB);
nodeC.Right(nodeB);
if(m_root_node==nodeA)
m_root_node=nodeC;
curr_node=nodeC.Parent();
}
else
{
//--- slight rotation to the right
nodeA=curr_node;
nodeB=nodeA.Right();
nodeB.Parent(nodeA.Parent());
tmp_node=nodeB.Parent();
if(tmp_node!=NULL)
{
if(tmp_node.Right()==nodeA)
tmp_node.Right(nodeB);
else
tmp_node.Left(nodeB);
}
else
m_root_node=nodeB;
nodeA.Parent(nodeB);
nodeA.Right(nodeB.Left());
tmp_node=nodeA.Right();
if(tmp_node!=NULL)
tmp_node.Parent(nodeA);
nodeB.Left(nodeA);
if(m_root_node==nodeA)
m_root_node=nodeB;
curr_node=nodeB.Parent();
}
}
else
{
//--- rotation to the left
tmp_node=curr_node.Left();
if(tmp_node.BalanceR()>tmp_node.BalanceL())
{
//--- great rotation to the left
nodeA=curr_node;
nodeB=nodeA.Left();
nodeC=nodeB.Right();
nodeC.Parent(nodeA.Parent());
tmp_node=nodeC.Parent();
if(tmp_node!=NULL)
{
if(tmp_node.Right()==nodeA)
tmp_node.Right(nodeC);
else
tmp_node.Left(nodeC);
}
else
m_root_node=nodeC;
nodeA.Parent(nodeC);
nodeB.Parent(nodeC);
nodeA.Left(nodeC.Right());
tmp_node=nodeA.Left();
if(tmp_node!=NULL)
tmp_node.Parent(nodeA);
nodeC.Right(nodeA);
nodeB.Right(nodeC.Left());
tmp_node=nodeB.Right();
if(tmp_node!=NULL)
tmp_node.Parent(nodeB);
nodeC.Left(nodeB);
if(m_root_node==nodeA)
m_root_node=nodeC;
curr_node=nodeC.Parent();
}
else
{
//--- small rotation to the left
nodeA=curr_node;
nodeB=nodeA.Left();
nodeB.Parent(nodeA.Parent());
tmp_node=nodeB.Parent();
if(tmp_node!=NULL)
{
if(tmp_node.Right()==nodeA)
tmp_node.Right(nodeB);
else
tmp_node.Left(nodeB);
}
else
m_root_node=nodeB;
nodeA.Parent(nodeB);
nodeA.Left(nodeB.Right());
tmp_node=nodeA.Left();
if(tmp_node!=NULL)
tmp_node.Parent(nodeA);
nodeB.Right(nodeA);
if(m_root_node==nodeA)
m_root_node=nodeB;
curr_node=nodeB.Parent();
}
}
}
}
}
//+------------------------------------------------------------------+
//| Writing tree to file |
//+------------------------------------------------------------------+
bool CTree::Save(const int file_handle)
{
//--- check
if(file_handle==INVALID_HANDLE)
return(false);
if(m_root_node==NULL)
return(true);
//--- result
return(m_root_node.SaveNode(file_handle));
}
//+------------------------------------------------------------------+
//| Reading tree from file |
//+------------------------------------------------------------------+
bool CTree::Load(const int file_handle)
{
//--- check
if(file_handle==INVALID_HANDLE)
return(false);
//--- create root node only
Clear();
Insert(CreateElement());
//--- result
return(m_root_node.LoadNode(file_handle,m_root_node));
}
//+------------------------------------------------------------------+
+174
View File
@@ -0,0 +1,174 @@
//+------------------------------------------------------------------+
//| TreeNode.mqh |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Object.mqh>
//+------------------------------------------------------------------+
//| Class CTreeNode. |
//| Purpose: Base class of node of binary tree CTree. |
//| Derives from class CObject. |
//+------------------------------------------------------------------+
class CTreeNode : public CObject
{
private:
CTreeNode *m_p_node; // link to node up
CTreeNode *m_l_node; // link to node left
CTreeNode *m_r_node; // link to node right
//--- variables
int m_balance; // balance of node
int m_l_balance; // balance of the left branch
int m_r_balance; // balance of the right branch
public:
CTreeNode(void);
~CTreeNode(void);
//--- methods of access to protected data
CTreeNode* Parent(void) const { return(m_p_node); }
void Parent(CTreeNode *node) { m_p_node=node; }
CTreeNode* Left(void) const { return(m_l_node); }
void Left(CTreeNode *node) { m_l_node=node; }
CTreeNode* Right(void) const { return(m_r_node); }
void Right(CTreeNode *node) { m_r_node=node; }
int Balance(void) const { return(m_balance); }
int BalanceL(void) const { return(m_l_balance); }
int BalanceR(void) const { return(m_r_balance); }
//--- method of identifying the object
virtual int Type(void) const { return(0x8888); }
//--- methods for controlling
int RefreshBalance(void);
CTreeNode *GetNext(const CTreeNode *node);
//--- methods for working with files
bool SaveNode(const int file_handle);
bool LoadNode(const int file_handle,CTreeNode *main);
protected:
//--- method for creating an instance of class
virtual CTreeNode *CreateSample(void) { return(NULL); }
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CTreeNode::CTreeNode(void) : m_p_node(NULL),
m_l_node(NULL),
m_r_node(NULL),
m_balance(0),
m_l_balance(0),
m_r_balance(0)
{
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CTreeNode::~CTreeNode(void)
{
//--- delete nodes of the next level
if(m_l_node!=NULL)
delete m_l_node;
if(m_r_node!=NULL)
delete m_r_node;
}
//+------------------------------------------------------------------+
//| Calculating the balance of the node |
//+------------------------------------------------------------------+
int CTreeNode::RefreshBalance(void)
{
//--- calculate the balance of the left branch
if(m_l_node==NULL)
m_l_balance=0;
else
m_l_balance=m_l_node.RefreshBalance();
//--- calculate the balance of the right branch
if(m_r_node==NULL)
m_r_balance=0;
else
m_r_balance=m_r_node.RefreshBalance();
//--- calculate the balance of the node
if(m_r_balance>m_l_balance)
m_balance=m_r_balance+1;
else
m_balance=m_l_balance+1;
//--- result
return(m_balance);
}
//+------------------------------------------------------------------+
//| Selecting next node |
//+------------------------------------------------------------------+
CTreeNode *CTreeNode::GetNext(const CTreeNode *node)
{
if(Compare(node)>0)
return(m_l_node);
//--- result
return(m_r_node);
}
//+------------------------------------------------------------------+
//| Writing node data to file |
//+------------------------------------------------------------------+
bool CTreeNode::SaveNode(const int file_handle)
{
bool result=true;
//--- check
if(file_handle==INVALID_HANDLE)
return(false);
//--- write left node (if it is available)
if(m_l_node!=NULL)
{
FileWriteInteger(file_handle,'L',SHORT_VALUE);
result&=m_l_node.SaveNode(file_handle);
}
else
FileWriteInteger(file_handle,'X',SHORT_VALUE);
//--- write data of current node
result&=Save(file_handle);
//--- write right node (if it is available)
if(m_r_node!=NULL)
{
FileWriteInteger(file_handle,'R',SHORT_VALUE);
result&=m_r_node.SaveNode(file_handle);
}
else
FileWriteInteger(file_handle,'X',SHORT_VALUE);
//--- successful
return(true);
}
//+------------------------------------------------------------------+
//| Reading node data from file |
//+------------------------------------------------------------------+
bool CTreeNode::LoadNode(const int file_handle,CTreeNode *main)
{
bool result=true;
short s_val;
CTreeNode *node;
//--- check
if(file_handle==INVALID_HANDLE)
return(false);
//--- read directions
s_val=(short)FileReadInteger(file_handle,SHORT_VALUE);
if(s_val=='L')
{
//--- read left node (if there is data)
node=CreateSample();
if(node==NULL)
return(false);
m_l_node=node;
node.Parent(main);
result&=node.LoadNode(file_handle,node);
}
//--- read data of current node
result&=Load(file_handle);
//--- read directions
s_val=(short)FileReadInteger(file_handle,SHORT_VALUE);
if(s_val=='R')
{
//--- read right node (if there is data)
node=CreateSample();
if(node==NULL)
return(false);
m_r_node=node;
node.Parent(main);
result&=node.LoadNode(file_handle,node);
}
//--- result
return(result);
}
//+------------------------------------------------------------------+