//+------------------------------------------------------------------+ //| TreeNode.mqh | //| Copyright 2000-2025, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #include //+------------------------------------------------------------------+ //| 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); } //+------------------------------------------------------------------+