Add files via upload
This commit is contained in:
@@ -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
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -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);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -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);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -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);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -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);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -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);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -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);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -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);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -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
@@ -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
@@ -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));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -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);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
Reference in New Issue
Block a user