下载MetaTrader 5

CTree

CTree 类是 CTreeNode 类及其子类的样本二叉树。

描述

类 CTree 可供操作 CTreeNode 类及其子类的样本二叉树。在类中, 实现了三元素添加/插入/删除选项以及搜索二叉树。此外, 还实现了文件操作方法。

注释, 在类 CTree 没有实现内存管理机制 (这点与类 CListCArrayObj 不同)。所有树节点被删除时内存一并释放。

声明

   class CTree : public CTreeNode

标称库文件

   #include <Arrays\Tree.mqh>

继承体系

  CObject

      CTreeNode

          CTree

类方法

属性

 

Root

获取树的根节点

创建一个新元素

 

CreateElement

创建一个新节点实例

填充

 

Insert

在树中添加节点

删除

 

Detach

从树里分离一个指定节点

删除

从树里删除一个指定节点

Clear

从树里删除所有节点

搜索

 

Find

在树里按样本搜索一个节点

输入/输出

 

virtual Save

保存所有树数据至文件

virtual Load

从文件里加载树数据

virtual Type

获取树类型的标识符

CTreeNode 类的子类树 �C 子类 CTree 得到实际应用。

类 CTree 的子类必须有一个预定义方法 CreateElement 用于创建子类 CTreeNode 的新样本。

我们来研究一个 CTree 子类的例子。

//+------------------------------------------------------------------+
//|                                                       MyTree.mq5 |
//|                        Copyright 2010, MetaQuotes Software Corp. |
//|                                       https://www.metaquotes.net/ |
//+------------------------------------------------------------------+
#property copyright "2010, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
//---
#include <Arrays\Tree.mqh>
#include "MyTreeNode.mqh"
//---
input int extCountedNodes = 100;
//+------------------------------------------------------------------+
//| 描述类 CMyTree derived from CTree。                      |
//+------------------------------------------------------------------+
//| Class CMyTree.                                                   |
//| 目的: 构造并遍历二叉树。   |
//+------------------------------------------------------------------+
class CMyTree : public CTree
  {
public:
   //--- 以自定义数据搜索二叉树的方法
   CMyTreeNode*        FindByLong(long find_long);
   //--- 创建树元素的方法
   virtual CTreeNode *CreateElement();
  };
//---
CMyTree MyTree;
//+------------------------------------------------------------------+
//| 创建新的树节点。                                    |
//| 输入:  无。                                                   |
//| 输出: 成功则为新树节点指针, 或是 NULL。            |
//| 备注: 无。                                                   |
//+------------------------------------------------------------------+
CTreeNode *CMyTree::CreateElement()
  {
   CMyTreeNode *node=new CMyTreeNode;
//---
   return(node);
  }
//+------------------------------------------------------------------+
//| 按照值 m_long 在列表里搜索元素。                    |
//| 输入:  find_long - 搜索值。                             |
//| 输出: 发现的元素指针, 或是 NULL。               |
//| 备注: 无。                                                   |
//+------------------------------------------------------------------+
CMyTreeNode* CMyTree::FindByLong(long find_long)
  {
   CMyTreeNode *res=NULL;
   CMyTreeNode *node;
//--- 创建树节点, 传递搜索参数
   node=new CMyTreeNode;
   if(node==NULLreturn(NULL);
   node.SetLong(find_long);
//---
   res=Find(node);
   delete node;
//---
   return(res);
  }
//+------------------------------------------------------------------+
//| 脚本 "类 CMyTree 测试"                                |
//+------------------------------------------------------------------+
//---  用于字符串初始化的数组
string str_array[11]={"p","oo","iii","uuuu","yyyyy","ttttt","rrrr","eee","ww","q","999"};
//---
int OnStart() export
  {
   int          i;
   uint         pos;
   int          beg_time,end_time;
   CMyTreeNode *node; //--- 类 CMyTreeNode 样本的临时指针
//---  
   printf("开始测试 %s。",__FILE__);
//--- 用数量为 extCountedNodes 的 MyTreeNode 类样本填满 MyTree。
   beg_time=GetTickCount();
   for(i=0;i<extCountedNodes;i++)
     {
      node=MyTree.CreateElement();
      if(node==NULL)
        {
         //--- 紧急出口
         printf("%s (%4d): 创建错误",__FILE__,__LINE__);
         return(__LINE__);
        }
      NodeSetData(node,i);
      node.SetLong(i);
      MyTree.Insert(node);
     }
   end_time=GetTickCount();
   printf("填充 MyTree 时间是 %d 毫秒。",end_time-beg_time);
//--- 创建临时树 TmpMyTree。
   CMyTree TmpMyTree;
//--- 分离 50% 树元素 (所有偶数)
//--- 并将它们添加到临时树 TmpMyTree。
   beg_time=GetTickCount();
   for(i=0;i<extCountedNodes;i+=2)
     {
      node=MyTree.FindByLong(i);
      if(node!=NULL)
         if(MyTree.Detach(node)) TmpMyTree.Insert(node);
     }
   end_time=GetTickCount();
   printf("从 MyTree 删除 %d 元素的时间是 %d 毫秒。",extCountedNodes/2,end_time-beg_time);
//--- 返回分离
   node=TmpMyTree.Root();
   while(node!=NULL)
     {
      if(TmpMyTree.Detach(node)) MyTree.Insert(node);
      node=TmpMyTree.Root();
     }
//--- 检查操作方法 Save(int file_handle);
   int file_handle;
   file_handle=FileOpen("MyTree.bin",FILE_WRITE|FILE_BIN|FILE_ANSI);
   if(file_handle>=0)
     {
      if(!MyTree.Save(file_handle))
        {
         //--- 写文件错误
         //--- 紧急出口
         printf("%s: 错误 %d 为 %d!",__FILE__,GetLastError(),__LINE__);
         //--- 离开前关闭文件!!!
         FileClose(file_handle);
         return(__LINE__);
        }
      FileClose(file_handle);
     }
//--- 检查操作方法 Load(int file_handle);
   file_handle=FileOpen("MyTree.bin",FILE_READ|FILE_BIN|FILE_ANSI);
   if(file_handle>=0)
     {
      if(!TmpMyTree.Load(file_handle))
        {
         //--- 读文件错误
         //--- 紧急出口
         printf("%s: 错误 %d 为 %d!",__FILE__,GetLastError(),__LINE__);
         //--- 离开前关闭文件!!!
         FileClose(file_handle);
         return(__LINE__);
        }
      FileClose(file_handle);
     }
//---
   MyTree.Clear();
   TmpMyTree.Clear();
//---
   printf("测试结束 %s。OK!",__FILE__);
//---
   return(0);
  }
//+------------------------------------------------------------------+
//| 节点内容输出至日志功能                   |
//+------------------------------------------------------------------+
void NodeToLog(CMyTreeNode *node)
  {
   printf("   %I64d,%f,'%s','%s'",
               node.GetLong(),node.GetDouble(),
               node.GetString(),TimeToString(node.GetDateTime()));
  }
//+------------------------------------------------------------------+
//| 用随机值 "填充" 节点功能                 |
//+------------------------------------------------------------------+
void NodeSetData(CMyTreeNode *node,int mode)
  {
   if(mode%2==0)
     {
      node.SetLong(mode*MathRand());
      node.SetDouble(MathPow(2.02,mode)*MathRand());
     }
   else
     {
      node.SetLong(mode*(long)(-1)*MathRand());
      node.SetDouble(-MathPow(2.02,mode)*MathRand());
     }
   node.SetString(str_array[mode%10]);
   node.SetDateTime(10000*mode);
  }

 


更新: 2017.03.22