Библиотека Generic классов - ошибки, описание, вопросы, особенности использования и предложения

 

С 6 декабря 2017 года в стандартную поставку MetaTrader 5 стали входить так называемые Generic-классы, реализующие эффективные алгоритмы для хранения и извлечения данных. Данная ветка создана для описания этих классов, примеров работы с ними а также для предложений по улучшению их работы.

Что такое Generic?  Generic это специальные шаблонные классы, которые могут хранить пользовательские типы данных. При этом идентификация типа происходит в момент компиляции, за счет чего достигается высокая производительность.

Почему именно Generic? Как правило, начинающие программисты знакомы только с одним типом коллекции: массивом. Но есть множество задач, где работа с массивом неэффективна. Представьте себе, что у нас есть массив, состоящий из миллиона уникальных идентификаторов, например тысяча ордеров. Как проверить, есть ли в этой тысячи ордеров, один орден с номером N? Если использовать один из generic-классов эту задачу можно выполнить почти мгновенно, за константное время, которое не будет зависеть от количества элементов среди которых будет происходить поиск. Есть и другие задачи, где правильный алгоритм из коллекции generic может оказаться быстрее алгоритма придуманного программистом.

Алгоритмы Generic. Ниже приведу таблицу generic-классов, с кратким описанием того, что они делают:

КлассОписание
CArrayListМассив, с автоматической переразметкой размера. Позволяет использовать преимущества массива без надобности контроля выхода за его пределы.
CHashMapМножество ключ-значение. Позволяет эффективно вставлять, извлекать и искать элементы по их ключу. Ключ должен быть уникальным. Например, CHashMap может мгновенно найти ордер с указанным номером, где номер используется в виде ключа. 
СHashSetМножество уникальных элементов. Позволяет делать все тоже самое, что и CHashMap, но не требует указания ключа. Элементы хранящиеся в этой коллекции не должны повторяться. При этом также осуществляется мгновенный поиск, извлечение и добавление элемента.
CLinkedListДвухсвязанный список. Позволяет легко вставлять и удалять элементы. Однако для поиска нужного элемента требуется время линейно зависящее от количества элементов в нем.
 CQueueКуча. Организует очередь типа FIFO 
 CStackСтек. Организует очередь типа LIFO
 CRedBlackTreeКрасно-черное дерево. Позволяет быстро (за логарифмическое время) вставлять элементы, извлекать и находить их. В отличии от CHashMap и CHashSet позволяет эффективно реализовать дополнительные алгоритмы отношения, типа больше чем, меньше чем, между и т.д.
 CSortedMapСортированное множество по ключу. Хранит значения ключ-значения. При этом ключ отсортирован. 
 CSortedSetСортированное множество по значению. Хранит упорядоченный набор значений.

Позже мы продолжим и рассмотрим особенности реализации этих классов.

 
Vasiliy Sokolov:

Представьте себе, что у нас есть массив, состоящий из миллиона уникальных идентификаторов, например тысяча ордеров. Как проверить, есть ли в этой тысячи ордеров, один орден с номером N? Если использовать один из generic-классов эту задачу можно выполнить почти мгновенно, за константное время, которое не будет зависеть от количества элементов среди которых будет происходить поиск.

С темой незнаком совсем. Но выделенное звучит алогично.

 

К сожалению библиотека только вышла и еще сыровата. Вот уже нашел первую ошибку в ней (ошибки буду посвечивать маркером важно):

Ошибка в 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:

... Но выделенное звучит алогично.

Это почему?

 
Vasiliy Sokolov:

Это почему?

Делать хэши, сортировать их по возрастанию. Но поиск в любом случае будет.

 
fxsaber:

С темой незнаком совсем. Но выделенное звучит алогично.

среднее время О(1) худшее O(n) и перформанс сильно зависит от хеша.
 
fxsaber:

Делать хэши ...

Давайте определимся с терминологией. Ничего мгновенного не бывает. Любая операция требует времени. Когда я говорю мгновенно я упрощаю, что бы начинающие программисты меня поняли. Если говорить строго, то есть несколько классов сложности, основные, с которыми мы будем иметь дело следующие:

  • Константная сложность cO(1).
  • Логарифмическая: сO(log n).
  • Линейная: cO(n).
  • Алгоритмы требующие не линейного времени выполнения.

Я намеренно ввел знак c - как некую константу, которая возникает при вычислении хеша, и прочих технических манипуляций. Но в данном случае обсуждение оптимизации константы c - это оффтоп данной ветки. Нас здесь интересует только generic классы и их применение на практике. 

 
fxsaber:

Делать хэши, сортировать их по возрастанию. Но поиск в любом случае будет.

Комбинатор:
среднее время О(1) худшее O(n) и перформанс сильно зависит от хеша.

+

p.s. в качестве иллюстрации ниже приведу пример, где этот самый перфоменс просядет до O(n), если неправильно работать с CHashMap.

 

Предлагаю упростить названия - сделать их более логичными. Пример, CArrayList всё таки Array или List в mql5 есть имплементация и того и другого?

Это всё провоцирует вопросы и непонятки. ИМХО, надо косить под stl, а не под C# или Java. Или убрать тогда впереди C, пусть будет просто ArrayList.


Если сделать нормальные названия:

- читабельность повысится в разы

- будет вырисовываться свой специфичный стиль mql5

- новички, смогут сразу ориентироваться в коде (так как stl входит в стандарт)

 
Vasiliy Sokolov:

...

Если можно примеры, например про поиск среди тысячи сделок.
Причина обращения: