174 lines
6.5 KiB
MQL5
174 lines
6.5 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| TreeNode.mqh |
|
|
//| Copyright 2000-2025, 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);
|
|
}
|
|
//+------------------------------------------------------------------+
|