通用类库 - 错误、说明、问题、使用功能和建议

 

自 2017 年 12 月 6 日起,MetaTrader 5 的标准交付 已包含所谓的 "通用类"(Generic classes),可实现数据存储和检索的高效算法。创建本主题的目的是描述这些类、使用它们的示例以及改进其工作的建议。

什么是通用类? 通用 类是可以存储自定义数据类型 的特殊模板类。类型识别在编译时进行,因此性能很高。

为什么要使用通用类? 一般来说,新手程序员只熟悉一种集合类型:数组。但在许多任务中,使用数组的效率很低。想象一下,我们有一个由一百万个唯一标识符组成的数组,例如,一千个订单。我们如何检查这一千份订单中是否有编号为 N 的订单呢?如果我们使用其中一个通用类,这项任务几乎可以立即执行,时间恒定,与搜索的元素数量无关。在其他任务中,使用通用类库中的正确算法可能比程序员发明的算法更快。

通用算法 下面是通用类的表格,并简要说明了它们的作用:

描述
CArrayList.一个数组,可自动重新划分大小。允许您利用数组的优势,而无需控制数组之外的内容。
现金图键值集。允许通过键值有效地插入、检索和搜索元素。键值必须是唯一的。例如,CHashMap 可以立即查找具有指定编号的订单,其中编号被用作键。
现金集唯一元素的集合。允许执行与 CHashMap 相同的操作,但不需要键。存储在此集合中的元素不得重复。它还允许即时搜索、检索和添加项目。
链表一个双链接列表。允许轻松插入和删除项目。不过,查找所需项目所需的时间与列表中的项目数成线性关系。
队列堆。组织一个先进先出类型的队列
堆栈堆栈。组织后进先出类型的队列
CRedBlackTree红黑树允许快速(对数时间内)插入元素、提取和查找元素。与 CHashMap 和 CHashSet 不同的是,它允许高效地实现其他关系算法,如大于、小于、之间 等。
CSortedMap按键排序的集合。存储键值。在这种情况下,键是排序的。
CSortedSet按值排序的集合。存储值的有序集合。

稍后我们将继续研究这些类的实现特性。

 
瓦西里-索科洛夫

想象一下,我们有一个由一百万个唯一标识符组成的数组,例如一千个订单。我们怎样才能检查在这一千个订单中是否有一个编号为N的订单?如果我们使用其中一个通用类,这个任务几乎可以立即完成,在一个恒定的时间内,这并不取决于我们要搜索的元素数量

对这个问题一点也不熟悉。但强调的内容听起来不符合逻辑。

 

不幸的是,该库刚刚发布,仍然是原始的。我已经发现了其中的第一个错误(我将按标记突出错误)。

CSortedSet中的错误。

//+------------------------------------------------------------------+
//| Class CSortedSet<T>.                                             |
//| Usage: Represents a collection of objects that is maintained in  |
//|        sorted order.                                             |
//+------------------------------------------------------------------+
template<typename T>
class CSortedSet: public ISet<T>
  {
   ...
   bool              TryGetMin(T &min)    { return(m_tree.TryGetMin(min)); }
   bool              TryGetMax(T &max)    { return(m_tree.TryGetMin(max)); }
   ...
  }

TryGetMax方法返回最小元素而不是最大元素,TryGetMin也是如此。

 
fxsaber:

...但强调的内容听起来不符合逻辑。

这是为什么呢?

 
瓦西里-索科洛夫

这是为什么呢?

制作哈希值,按升序排序。但无论如何,搜索会出现在那里。

 
fxsaber:

对这个问题一点也不熟悉。但强调的内容听起来不符合逻辑。

平均时间为O(1),最差为O(n),性能高度依赖于哈希值。
 
fxsaber:

制作哈希值...

让我们定义一下术语。没有什么是瞬间的。任何操作都需要时间。当我说即时的 时候,我把它简化了,以便让新手程序员理解我。严格说来,有几类复杂性,我们要处理的主要是以下几类。

  • 恒定复杂度cO(1)。
  • 对数:cO(log n)。
  • 线性:cO (n)。
  • 需要非线性运行时间的算法。

我特意引入了一个c 符号-- 作为一种常数,在计算哈希值和其他技术操作时出现。但在这种情况下,关于恒定C 的优化的讨论已经偏离了这个主题。我们在这里只对通用类和它们在实践中的应用感兴趣。

 
fxsaber:

制作哈希值,按升序排序。但无论如何都会有一个搜索。

组合器
平均时间为O(1)最差为O(n),性能高度依赖于哈希值。

+

p.s. 为了说明问题,这里有一个例子,如果你不正确处理CHashMap,同样的性能会下降到O(n)。

 
瓦西里-索科洛夫

写得很清楚

看看突出显示的是什么。

 

我建议简化名称--使其更符合逻辑。例如,在mql5中,CArrayList 是一个数组还是List,是两者的实现?

这一切导致了问题和困惑。IMHO,我们应该使用stl而不是C#或Java。或者去掉前面的C,让它成为ArrayList。


如果你做正常的名字。

- 可读性将提高许多倍。

- 你会有你自己特定的mql5风格。

- 初学者将能够立即浏览代码(因为stl被包含在标准中)。

 
瓦西里-索科洛夫

...

如果你能举出例子,比如说关于在成千上万的交易中搜索。