Глобальные массивы: технология поиска
В прошлом выпуске я привел код функции SearchItem(), с помощью которой можно найти элемент в массиве.
Эта функция возвращает:
- индекс найденного элемента в массиве, если элемент найден; или
- 0 - если элемента в массиве нет; или
- -1 - если произошла какая-то ошибка.
Для того, чтобы понять принцип работы этой функции, будет полезно рассказать о различных технологиях поиска.
Прежде всего код функции SearchItem() начинается с того, что мы локируем критическую секцию, чтобы обеспечить монопольный доступ к данным массива:
// Залокировать критическую секцию string critical_section = array+"Lock"; if (Lock(critical_section)!=0) return(-1);
Для осуществления поиска мы должны знать количество элементов в массиве:
// Количество элементов массива хранится в переменной с именем, // равным имя массива + "Count" string gv_count; gv_count = array+"Count"; int count, err; // Если глобальная переменная не существует, то элементов нет if (!GlobalVariableCheck(gv_count)) { err = GetLastError(); if (err!=0) { // Разлокировать критическую секцию Unlock(critical_section); // Вывести сообщение об ошибке и выйти Print("SearchItem()->GlobalVariableCheck(): ошибка ", err); return(-1); } else count = 0; } else // переменная существует, получим количество элементов count = GlobalVariableGet(gv_count);
После этого мы смотрим, отсортирован ли массив:
- Если массив неотсортированный, то просто перебираем все элементы.
- Если массив отсортированный, то используем технологию двоичного поиска.
Технология поиска простым перебором:
int i; for (i=1; i<=count; i++) if (item==GlobalVariableGet(array+DoubleToStr(i, 0))) { // Разлокировать критическую секцию Unlock(critical_section);return(i);
}
Технология двоичного поиска:
- Левая граница поиска - первый элемент, правая граница поиска - последний эелемент.
- Берем элемент, который находится посередине между левой и правой границами.
- Если этот элемент меньше того, который мы ищем, то сдвигаем левую границу поиска к середине нашего диапазона (т.к. однозначно, что искомый элемент находится выше серединного). В противном случае - сдвигаем правую границу поиска к середине диапазона. Каждый раз диапазон поиска уменьшается в два раза.
- Повторяем шаги 2 и 3, пока диапазон больше 2 элементов
Такая технология поиска гарантирует быстрое нахождение элемента в отсортированном массиве. Например, в массиве из 1,000 элементов мы найдем элемент за 10 итераций, а в массиве из 1,000,000,000 элементов - за 30 итераций. В то время как поиск путем простого перебора даст тот же результат в среднем за 500 и 500,000,000 итераций соответственно. Выигрыш в скорости очень ощутим.
Напомню кусок кода, который осуществляет двоичный поиск в отсортированном массиве:
int pos1, pos2, mid; pos1 = 1; pos2 = count; while (pos1+1<pos2) { mid = (pos1+pos2)/2; if (item>GlobalVariableGet(array+DoubleToStr(mid, 0))) pos1 = mid; else pos2 = mid; } if (GlobalVariableGet(array+DoubleToStr(pos1, 0))==item) { // Разлокировать критическую секцию Unlock(critical_section); return(pos1); } if (GlobalVariableGet(array+DoubleToStr(pos2, 0))==item) { // Разлокировать критическую секцию Unlock(critical_section); return(pos2); } }
В следующем выпуске я расскажу о том, как с помощьюе функции GetItem() получить значение элемента в определенной позиции массиве.
Все статьи по теме "Пишем советников для MetaTrader 4".
- Механическая торговая система - миф или реальность?
- С чего начать при написании советника:
- Создаем нового советника - Настраиваем параметры. - Язык MetaQuotes Language 4: