CTree

CTree はCTreeNode とその派生クラスを節点とする二進木のクラスです。

説明

CTree は CTreeNode クラスインスタンスとその派生クラスを節点(ノード)とした二進木の操作を提供します。ツリー要素の追加/挿入/削除のオプションとツリー内の検索は、クラスに実装されています。ファイル操作のメソッドも実装されています。

CTree では動的メモリ管理は実装されていません(これは CList 及び CArrayObj とは異なります)。全てのツリーノードは、メモリ解放で削除されます。

宣言

  class CTree : public CTreeNode

タイトル

  #include <Arrays\Tree.mqh>

継承階層

  CObject

      CTreeNode

          CTree

クラスメソッド

属性

 

Root

ツリーの根(ルート)を取得します。

新しい要素の作成

 

CreateElement

ノードの新しいインスタンスを作成します。

書き込み

 

Insert

ツリーにノードを追加します。

削除

 

Detach

指定されたノードをツリーから取り外します。

Delete

指定されたノードをツリーから削除します。

Clear

ツリーの全てのノードを削除します。

検索

 

Find

ツリー内でサンプルによってノードを探します。

入出力

 

virtual Save

全てのツリーデータをファイルに保存します。

virtual Load

ファイルからツリーデータを読み込みます。

virtual Type

ツリー型の識別子を取得します。

クラスから継承されたメソッド CObject

Prev, Prev, Next, Next, Compare

クラスから継承されたメソッド 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;
//+------------------------------------------------------------------+
//| CTree.から派生された CMyTree クラスを記述する                      |
//+------------------------------------------------------------------+
//| 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("Start test %s.",__FILE__);
//--- MyTree に extCountedNodes 個の MyTreeNode クラスインスタンスのノードを書き込む
  beg_time=GetTickCount();
  for(i=0;i<extCountedNodes;i++)
    {
     node=MyTree.CreateElement();
    if(node==NULL)
       {
        //--- 緊急終了
        printf("%s (%4d): create error",__FILE__,__LINE__);
        return(__LINE__);
       }
     NodeSetData(node,i);
     node.SetLong(i);
     MyTree.Insert(node);
    }
  end_time=GetTickCount();
  printf("Filling time of MyTree is %d ms.",end_time-beg_time);
//--- 一時的な TmpMyTree ツリーを作成する
  CMyTree TmpMyTree;
//--- 半分(偶数)のツリー要素を取り外す
//--- 一時的な 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("Deletion time of %d elements from MyTree is %d ms.",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: Error %d in %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: Error %d in %d!",__FILE__,GetLastError(),__LINE__);
        //--- 終了前にファイルを閉じる
        FileClose(file_handle);
        return(__LINE__);
       }
    FileClose(file_handle);
    }
//---
  MyTree.Clear();
  TmpMyTree.Clear();
//---
  printf("End test %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);
 }