Бакнелл Джулиан М.
Шрифт:
В приведенном алгоритме существуют несколько "странных" шагов, которые требуют дополнительных объяснений. Так, например, шаги 5, 6, 7 и 8, на которых вычисляется значение переменной NewNode, - для чего они нужны? Прежде всего, здесь вычисляется размер нового узла. Как вы, наверное, помните, мы пытаемся создать список с требуемым количеством узлов каждого уровня. Узел уровня 0 должен создаваться в трех четвертях всех случаев, узел уровня 1 - в трех шестнадцатых всех случаев и т.д. Эти вычисления выполняются в цикле на шагах 5, 6 и 7. Во-вторых, на шаге 8 выполняется проверка того, что мы не вышли за границы максимального уровня списка. Не имеет смысла создавать узел, который находится на намного более высоком уровне, нежели текущий максимальный уровень. Поэтому максимальное значение уровня ограничивается увеличением уровня на единицу.
Шаг 2 также заслуживает отдельного рассмотрения. Фактически, в нем утверждается, что в списке с пропусками не могут храниться повторяющиеся элементы или, если выражаться более строго, элементы, в результате сравнения которых получается равенство. Почему? Представьте себе, что имеется список с пропусками, содержащий 42 узла, все значения которых равны а. В таком случае, что будет означать фраза: "Поиск узла а"? Учитывая саму природу списка с пропусками, на первом шаге поиска при переходе, скажем, на узел 35 будет найдено искомое значение а. Очевидно, что оно не будет ни первым в списке, ни последним - просто одним из 42 имеющихся в списке. Нужно ли в алгоритм вводить прохождение списка в обратном направлении, пока не будет найден первый узел со значением al Кто-то может сказать, что узлы с равными значениями должны находиться в списке в том порядке, в котором они вставлялись. Это означает, что при вставке элемента он будет добавляться в конец последовательности узлов с равными значениями, а при поиске нужно будет находить первый из повторяющихся узлов. Для алгоритма вставки при понижении уровней нужно сохранять список "предыдущих узлов". Эту операцию выполнить сложнее. По мнению автора книги, излишняя сложность алгоритмов для обеспечения возможности хранения в списке с пропусками узлов с одинаковыми значениями себя совершенно не оправдывает. Будем считать, что если существует вероятность повторения узлов, то мы знаем, как их различать между собой. В противном случае, они будут трактоваться как действительно один и тот же узел. Если мы можем различать повторяющиеся узлы, то можно предположить, что такая же возможность заложена и в функции сравнения. Следовательно, узлы уже не будут считаться повторениями.
В листинге 6.16 приведена реализация метода Add для класса списка с пропусками. В качестве генератора случайных чисел используется минимальный стандартный генератор, который мы изучали в первой части главы. Во всем остальном реализация следует алгоритму, описанному выше.
Листинг 6.16. Вставка в список с пропусками
procedure TtdSkipList.Add(aItem : pointer);
var
i, Level : integer;
NewNode : PskNode;
BeforeNodes : TskNodeArray;
begin
{выполнить поиск узла и заполнить значениями массив BeforeNodes}
if slSearchPrim(aItem, BeforeNodes) then
slError(tdeSkpLstDupItem, 'Add');
{вычислить уровень для нового узла}
Level := 0;
while (Level <= MaxLevel) and (FPRNG.AsDouble < 0.25) do inc(Level);
{если мы вышли за границы максимального уровня, сохранить новое значение в качестве максимального уровня}
if (Level > MaxLevel) then
inc(FMaxLevel);
{выделить память для нового узла}
NewNode := slAllocNode(Level);
NewNode^.sknData := aItem;
{восстановить указатели для уровня 0 - двухсвязный список}
NewNode^.sknPrev := BeforeNodes[0];
NewNode^.sknNext[0] := BeforeNodes[0]^.sknNext[0];
BeforeNodes[0]^.sknNext[0] := NewNode;
NewNode^.sknNext[0]^.sknPrev := NewNode;
{восстановить указатели для других уровней - односвязные списки}
for i := 1 to Level do
begin
NewNode^.sknNext[i] := BeforeNodes[i]^.sknNext[i];
BeforeNodes[i]^.sknNext[i] := NewNode;
end;
{теперь в список с пропусками добавлен новый узел}
inc(FCount);
end;
Обратите внимание, что проверка в самом начале метода необходима для того, чтобы убедиться, что в списке не будет повторяющихся элементов. Кроме того, наличие повторяющихся элементов существенно уложило бы операцию удаления.
Удаление из списка с пропусками
Алгоритм удаления узла из списка с пропусками достаточно прост, несмотря на его длину. Он выглядит следующим образом:
1. Найти удаляемый узел с помощью обычного алгоритма поиска.
2. Предположим, что узел находится на уровне i. Сохранить узел, расположенный перед удаляемым и находящийся на том же уровне, что и i-тый элемент в массиве. Установить значение переменной LevelNumber равным i, а предыдущий узел записать в переменную BeforeNode.
3. Уменьшить значение переменной LevelNumber на единицу.
4. Если переменная LevelNumber содержит отрицательное значение, перейти к шагу 7.
5. Начиная с узла BeforeNode, переходить по указателям уровня LevelNumber вплоть до достижения удаляемого узла. При переходе по указателям уровня LevelNumber отслеживать родительские узлы всех проходимых узлов, что позволит идентифицировать узел, предшествующий удаляемому на уровне LevelNumber.
6. Записать узел, предшествующий удаляемому, в массив в элемент LevelNumber. Установить переменную BeforeNode равной этому узлу. Перейти к шагу 3.
7. Если мы достигли этого шага, у нас имеется массив предшествующих узлов для удаляемого узла для уровней от i до 0. Выполнить стандартную операцию "удалить после" для связного списка на каждом уровне.
Шаг 5 гарантированно будет работать (т.е. мы всегда найдем удаляемый узел), поскольку узел уровня n содержит указатели на всех уровнях до уровня n включительно.
Жанры
- Романы
- Приключения
- Детективы
- Техно триллер
- Дамский детективный роман
- Исторические детективы
- Классические детективы
- Шпионские детективы
- Триллеры
- Юридический триллер
- Крутой детектив
- Полицейские детективы
- Медицинский триллер
- Иронические детективы
- Боевики
- Криминальные детективы
- Политические детективы
- Маньяки
- Зарубежные детективы
- Прочие Детективы
- Спецслужбы
- Драматургия
- Фантастика
- Хентай
- Ранобэ
- Сянься
- Дорама
- Уся
- Аниме
- Космоопера
- Юмористическая фантастика
- Боевая фантастика
- Героическая фантастика
- Технофэнтези
- Готический роман
- Социально-философская фантастика
- Попаданцы
- Историческая фантастика
- Ироническая фантастика
- Зарубежная фантастика
- Историческое фэнтези
- Юмористическое фэнтези
- Детективная фантастика
- Эпическая фантастика
- Мистика
- Космическая фантастика
- Фантастика: прочее
- Постапокалипсис
- Научная фантастика
- Киберпанк
- Альтернативная история
- Ненаучная фантастика
- РПГ
- Стимпанк
- Ироническое фэнтези
- Ужасы и мистика
- Сказочная фантастика
- Фэнтези
- Городское фэнтези
- Эзотерика
- Проза
- Военная проза
- Легкая проза
- Сентиментальная проза
- Советская классическая проза
- Антисоветская литература
- Афоризмы
- Эпистолярная проза
- Новелла
- Семейный роман
- Рассказ
- Классическая проза
- Эпопея
- Эссе
- Проза прочее
- Повесть
- Магический реализм
- Современная проза
- Контркультура
- Роман
- Историческая проза
- Русская классическая проза
- Феерия
- Стихи и поэзия
- Юмор
- Дом и досуг
- Рыбалка
- Охота
- Здоровье детей
- Домашние животные
- Воспитание детей
- Отдых / туризм
- Зарубежная прикладная литература
- Прочее домоводство
- Прикладная литература
- Домашнее хозяйство
- Кулинария
- Медицина и здоровье
- Сделай сам
- Спорт
- Хобби и ремесла
- Образовательная литература
- Сад и Огород
- Здоровье и красота
- Развлечения
- Коллекционирование
- Секс / секс-руководства
- Образование и наука
- Боевые искусства
- Органическая химия
- Обществознание
- Военная история
- Ветеринария
- Ораторское искусство / риторика
- Физика
- Химия
- Семейная психология
- Военная техника и вооружение
- Иностранные языки
- Прочая научная литература
- Психотерапия и консультирование
- Биохимия
- Cпецслужбы
- Астрономия и Космос
- Школьные учебники
- Учебная и научная литература
- Учебники
- Государство и право
- Психология
- Литературоведение
- История
- Научно-популярная литература
- Политика
- Детская психология
- Юриспруденция
- Шпаргалки
- Педагогика
- Физическая химия
- Медицина
- Биофизика
- Языкознание
- Зарубежная образовательная литература
- Зоология
- Геология и география
- Краткое содержание
- Зарубежная психология
- Саморазвитие / личностный рост
- Технические науки
- Религиоведение
- Военное дело
- Личная эффективность
- Аналитическая химия
- Рефераты
- Экология
- Философия
- Альтернативная медицина
- Математика
- Культурология
- Военное дело: прочее
- Ботаника
- Биология
- Словари и Энциклопедии
- Финансы и бизнес
- Отраслевые издания
- Бухучет и аудит
- Недвижимость
- Деловая литература
- Ценные бумаги
- Внешнеэкономическая деятельность
- Торговля
- Зарубежная деловая литература
- О бизнесе популярно
- Стартапы и создание бизнеса
- Корпоративная культура
- Управление, подбор персонала
- Маркетинг, PR, реклама
- Личные финансы
- Работа с клиентами
- Менеджмент
- Интернет-бизнес
- Поиск работы, карьера
- Малый бизнес
- Делопроизводство
- Государственное и муниципальное управление
- Банковское дело
- Экономика
- Книги по IT
- Техника
- Древние книги
- Документальное
- Прочее
- Интерьеры
- Газеты и журналы
- Театр
- Музыка
- Комиксы / манга
- Зарубежная классика
- Современная зарубежная литература
- Изобразительное искусство, фотография
- Мода и стиль
- Искусство и Дизайн
- Зарубежная литература о культуре и искусстве
- Фанфик
- Подростковая литература
- Шахматы
- Кино
- Культура и искусство
- Недописанное
- Классическая литература
- Без Жанра
- Народные
- Книги Для Детей
- Детские остросюжетные
- Сказки
- Детские стихи
- Прочая детская литература
- Детская образовательная литература
- Книги для дошкольников
- Детская фантастика
- Детские детективы
- Книга-игра
- Детский фольклор
- Буквари
- Детская проза
- Детская познавательная и развивающая литература
- Внеклассное чтение
- Зарубежные детские книги
- Детские приключения