CTree
CTree
CTree 类是 CTreeNode 类及其子类的样本二叉树。
描述
类 CTree 可供操作 CTreeNode 类及其子类的样本二叉树。在类中, 实现了三元素添加/插入/删除选项以及搜索二叉树。此外, 还实现了文件操作方法。
注释, 在类 CTree 没有实现内存管理机制 (这点与类 CList 和 CArrayObj 不同)。所有树节点被删除时内存一并释放。
声明
class CTree : public CTreeNode标称库文件
#include <Arrays\Tree.mqh>继承体系
CTree
类方法
| 属性 | |
|---|---|
| Root | 获取树的根节点 |
| 创建一个新元素 | |
| CreateElement | 创建一个新节点实例 |
| 填充 | |
| Insert | 在树中添加节点 |
| 删除 | |
| Detach | 从树里分离一个指定节点 |
| 删除 | 从树里删除一个指定节点 |
| Clear | 从树里删除所有节点 |
| 搜索 | |
| Find | 在树里按样本搜索一个节点 |
| 输入/输出 | |
| virtual Save | 保存所有树数据至文件 |
| virtual Load | 从文件里加载树数据 |
| virtual Type | 获取树类型的标识符 |
方法继承自类 CTreeNode
: Parent, Parent, Left, Left, Right, Right, Balance, BalanceL, BalanceR, RefreshBalance, GetNext, SaveNode, LoadNode
CTreeNode 类的子类树 子类 CTree 得到实际应用。
类 CTree 的子类必须有一个预定义方法 CreateElement 用于创建子类 CTreeNode 的新样本。
我们来研究一个 CTree 子类的例子。
//+------------------------------------------------------------------+
//| MyTree.mq5 |
//| Copyright 2000-2024, MetaQuotes Ltd. |
//| 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==NULL) return(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);
}