Часть полного текста документа:Создание эффективной реализации сортированного списка с использованием generics Сергей Смирнов (Serginio1) Так случилось, что я стал программистом 1С. Все прекрасно в этой среде, за исключением скорости. Эту проблему можно решить только одним способом: прямым доступом к файлам и обработкой результатов на компилируемом языке в памяти. Так, для группирования данных нужны алгоритмы поиска и вставки. И мое сознание, отягощенное бухгалтерским учетом, не нашло ничего лучшего, чем использовать аналог TList (SortedList), представляющий собой динамический массив со свойствами "емкость" и "количество элементов". Упорядоченность в этом массиве поддерживается с помощью компараторов, а при поиске используется алгоритм половинного деления с поиском нужной позиции i по ключу с условием (Items[i]>=Key) AND (Items[i-1] 1) { // Перебираем грани int hi = _pageCount - 1; int lo = 0; while (lo > 1; int result = _comparer.Compare(NodeArray[i].Key, key); if (result < 0) lo = i + 1; else { hi = i - 1; if (result == 0) { // Ключ найден на 2 уровне. Устанавливаем текущую // страницу CurrentLeafPage. _currentPageIndex = i; CurrentLeafPage = NodeArray[_currentPageIndex].ChildPage; _selected = true; return true; } } } // Ключ не найден на 2 уровне. // Проверяем на возможность того, что искомый ключ - // наименьший из имеющихся в объекте. if (hi < 0) { // Данный ключ меньше наименьшего хранимого ключа. // Встаем на самый первый элемент двухуровневого массива _currentPageIndex = 0; CurrentLeafPage = NodeArray[_currentPageIndex].ChildPage; _selected = false; // Возвращаем информацию о том, что ключ не найден. return false; } else { // Данный ключ попадает в диапазон ключей нижележащей страницы. // Изменяем текущую страницу CurrentLeafPage на найденную дочернюю // страницу CurrentLeafPage = NodeArray[_currentPageIndex].ChildPage; // Устанавливаем текущий индекс ключа на листовой странице в 1, // т.к. 0 уже проверяли. _currentElementIndex = 1; } } // Пытаемся найти индекс искомого ключа или индекс, в котором он должен // был находиться. hi = CurrentLeafPage.Count - 1; lo = _currentElementIndex; while (lo > 1; int result = _comparer.Compare(CurrentLeafPage.PageItems[i].Key, key); if (result < 0) lo = i + 1; else { hi = i - 1; if (result == 0) { // Нашли! _currentElementIndex = i; _selected = true; return true; } } } // Не нашли... _selected = false; // Помещаем в _currentElementIndex позицию в которую // можно добавить элемент с искомым ключом. _currentElementIndex = lo; return false; } // Процедура вставки в текущую позицию private void Insert(K Key) { // Вставляем ключ в текущую позицию, расширяя тем самым массив на 1 элемент. // Сдвигаем элементы, чтобы освободить место для вставляемого. Array.Copy(CurrentLeafPage.PageItems, _currentElementIndex, CurrentLeafPage.PageItems, _currentElementIndex + 1, CurrentLeafPage.Count - _currentElementIndex); // Увеличиваем количество хранимых элементов на странице и вставляем ключ. CurrentLeafPage.Count++; CurrentLeafPage.PageItems[_currentElementIndex].Key = Key; if (_currentElementIndex==0) NodeArray[_currentPageIndex].Key = key; version++; // Произошли изменения, увеличиваем текущую версию. // // Если текущая страница листовая полностью заполнена, // то существуют 2 варианта. ............ |