- •Что я должен предварительно знать?
- •Какая версия Delphi мне нужна?
- •Что и где я могу найти в книге, или, другими словами, из чего состоит эта книга?
- •Глава 11 сконцентрирована вокруг нескольких технологий сжатия. Подробно рассматриваются такие алгоритмы сжатия, как Шеннона‑Фано, Хаффмана, с применением скошенного дерева и lz77.
- •От изготовителя fb2.
- •Благодарности
- •Глава 1. Что такое алгоритм?
- •Что такое алгоритм?
- •Анализ алгоритмов
- •О‑нотация
- •Лучший, средний и худший случаи
- •Алгоритмы и платформы
- •Виртуальная память и страничная организация памяти
- •Пробуксовка
- •Локальность ссылок
- •Кэш процессора
- •Выравнивание данных
- •Пространство или время
- •Длинные строки
- •Использование ключевого слова const
- •Осторожность в отношении автоматического преобразования типов
- •Тестирование и отладка
- •Утверждения
- •Комментарии
- •Протоколирование
- •Трассировка
- •Анализ покрытия
- •Тестирование модулей
- •Отладка
- •Глава 2. Массивы.
- •Массивы
- •Типы массивов в Delphi
- •Стандартные массивы
- •Динамические массивы
- •Новые динамические массивы
- •Класс tList, массив указателей
- •Краткий обзор класса tList
- •Класс TtdObjectList
- •Массивы на диске
- •Глава 3. Связные списки, стеки и очереди
- •Односвязные списки
- •Узлы связного списка
- •Создание односвязного списка
- •Вставка и удаление элементов в односвязном списке
- •Соображения по поводу эффективности
- •Использование начального узла
- •Использование диспетчера узлов
- •Класс односвязного списка
- •Двухсвязные списки
- •Вставка и удаление элементов в двухсвязном списке
- •Использование начального и конечного узлов
- •Использование диспетчера узлов
- •Класс двухсвязного списка
- •Достоинства и недостатки связных списков
- •Стеки на основе односвязных списков
- •Стеки на основе массивов
- •Пример использования стека
- •Очереди
- •Очереди на основе односвязных списков
- •Очереди на основе массивов
- •Глава 4. Поиск.
- •Процедуры сравнения
- •Последовательный поиск
- •Массивы
- •Связные списки
- •Бинарный поиск
- •Массивы
- •Связные списки
- •Вставка элемента в отсортированный контейнер
- •Глава 5. Сортировка
- •Алгоритмы сортировки
- •Тасование массива tList
- •Основы сортировки
- •Самые медленные алгоритмы сортировки
- •Пузырьковая сортировка
- •Шейкер‑сортировка
- •Сортировка методом выбора
- •Сортировка методом вставок
- •Быстрые алгоритмы сортировки
- •Сортировка методом Шелла
- •Сортировка методом прочесывания
- •Самые быстрые алгоритмы сортировки
- •Сортировка слиянием
- •Быстрая сортировка
- •Сортировка слиянием для связных списков
- •Глава 6. Рандомизированные алгоритмы.
- •Генерация случайных чисел
- •Критерий хи‑квадрат
- •Метод средних квадратов
- •Линейный конгруэнтный метод
- •Тестирование
- •Тест на однородность
- •Тест на пропуски
- •Тест "покер"
- •Тест "сбор купонов"
- •Результаты выполнения тестов
- •Комбинирование генераторов
- •Аддитивные генераторы
- •Тасующие генераторы
- •Выводы по алгоритмам генерации случайных чисел
- •Другие распределения случайных чисел
- •Списки с пропусками
- •Поиск в списке с пропусками
- •Вставка в список с пропусками
- •Удаление из списка с пропусками
- •Полная реализация класса связного списка
- •Глава 7. Хеширование и хеш‑таблицы
- •Функции хеширования
- •Простая функция хеширования для строк
- •Функции хеширования pjw
- •Разрешение конфликтов посредством линейного зондирования
- •Преимущества и недостатки линейного зондирования
- •Удаление элементов из хеш‑таблицы с линейным зондированием
- •Класс хеш‑таблиц с линейным зондированием
- •Другие схемы открытой адресации
- •Квадратичное зондирование
- •Псевдослучайное зондирование
- •Двойное хеширование
- •Разрешение конфликтов посредством связывания
- •Преимущества и недостатки связывания
- •Класс связных хеш‑таблиц
- •Разрешение конфликтов посредством группирования
- •Хеш‑таблицы на диске
- •Расширяемое хеширование
- •Глава 8. Бинарные деревья.
- •Создание бинарного дерева
- •Вставка и удаление с использованием бинарного дерева
- •Перемещение по бинарному дереву
- •Обход в ширину, симметричный обход и обход в глубину
- •Обход по уровням
- •Реализация класса бинарных деревьев
- •Деревья бинарного поиска
- •Вставка в дереве бинарного поиска
- •Удаление из дерева бинарного поиска
- •Реализация класса дерева бинарного поиска
- •Перекомпоновка дерева бинарного поиска
- •Скошенные деревья
- •Реализация класса скошенного дерева
- •Красно‑черные деревья
- •Вставка в красно‑черное дерево
- •Удаление из красно‑черного дерева
- •Глава 9. Очереди по приоритету и пирамидальная сортировка.
- •Очередь по приоритету
- •Первая простая реализация
- •Вторая простая реализация
- •Сортирующее дерево
- •Вставка в сортирующее дерево
- •Удаление из сортирующего дерева
- •Реализация очереди по приоритету при помощи сортирующего дерева
- •Пирамидальная сортировка
- •Алгоритм Флойда
- •Завершение пирамидальной сортировки
- •Расширение очереди по приоритету
- •Восстановление свойства пирамидальное
- •Отыскание произвольного элемента в сортирующем дереве
- •Реализация расширенной очереди по приоритету
- •Глава 10. Конечные автоматы и регулярные выражения.
- •Конечные автоматы
- •Использование конечного автомата: синтаксический анализ
- •Синтаксический анализ файлов с разделяющими запятыми
- •Детерминированные и недетерминированные конечные автоматы
- •Регулярные выражения
- •Использование регулярных выражений
- •Синтаксический анализ регулярных выражений
- •Компиляция регулярных выражений
- •Сопоставление строк с регулярными выражениями
- •Глава 11. Сжатие данных.
- •Представление данных
- •Сжатие данных
- •Типы сжатия
- •Потоки битов
- •Сжатие с минимальной избыточностью
- •Кодирование Шеннона‑Фано
- •Кодирование Хаффмана
- •Кодирование с использованием скошенного дерева
- •Сжатие с использованием словаря
- •Описание сжатия lz77
- •Особенности кодирования литеральных символов и пар расстояние/длина
- •Восстановление с применением алгоритма lz77
- •Сжатие lz77
- •Глава 12. Дополнительные темы.
- •Алгоритм считывания‑записи
- •Алгоритм производителей‑потребителей
- •Модель с одним производителем и одним потребителем
- •Модель с одним производителем и несколькими потребителями
- •Поиск различий между двумя файлами
- •Вычисление lcs двух строк
- •Вычисление lcs двух файлов
- •Список литературы
Двухсвязные списки
После достаточно подробных исследований односвязных списков можно переходить к рассмотрению двухсвязных списков. Как и в случае с односвязными списками, здесь имеется набор связанных между собой узлов, но помимо ссылки на следующий узел существует ссылка и на предыдущий узел:
type
PSimpleNode = ^TSimpleNode;
TSimpleNode = record
Next : PSimpleNode;
Prior : PSimpleNode;
Data : SomeDataType;
end;
Таким образом, двухсвязный список позволяет двигаться по узлам не только вперед, по ссылкам Next, но и назад, по ссылкам Prior. Схематично двухсвязный список показан на рис. 3.4.
Рисунок 3.4. Двухсвязный список
Вставка и удаление элементов в двухсвязном списке
Каким образом вставлять новый узел в двухсвязный список? В односвязном списке для этого нужно было разорвать одну ссылку и вставить две новых, а для двухсвязного списка потребуется разорвать две ссылки и вставить четыре новых. Причем вставку можно выполнять как перед, так и после определенного элемента, поскольку указатель Prior позволяет проходить список в обратном направлении. Фактически операцию "вставить перед" можно запрограммировать как "перейти к предыдущему узлу и вставить после". Поэтому в главе мы рассмотрим только операцию "вставить после".
Ссылка Next нового узла устанавливается на узел, расположенный после заданного узла, а ссылка Next заданного узла устанавливается на новый узел. Для установки обратных ссылок ссылка Prior нового узла устанавливается на заданный узел, а ссылка Prior узла, следующего за новым, устанавливается на новый узел. В коде это выглядит следующим образом:
var
GivenNode, NewNode : PSimpleNode;
begin
• • •
New(NewNode);
.. задать значение поля Data ..
NewNode^.Next := GivenNode^.Next;
GivenNode^.Next := NewNode;
NewNode^.Prior := GivenNode;
NewNode^.Next^.Prior := NewNode;
В случае с удалением проще всего удалить узел, находящийся после заданного узла. Необходимо установить ссылку Next заданного узла на узел, находящийся после удаляемого, а ссылку Prior узла, находящегося после удаляемого, на заданный узел.
Рисунок 3.5. Вставка нового узла в двухсвязный список
После этих операций удаляемый узел исключен из списка, и его можно удалить. В коде это выглядит следующим образом:
var
GivenNode, NodeToGo : PSimpleNode;
begin
• • •
NodeToGo := GivenNode^.Next;
GivenNode^.Next := NodeToGo^.Next;
NodeToGo^.Next^.Prior := GivenNode;
Dispose(NodeToGo);
Как и для односвязных списков, здесь для обеих операций существуют специальные случаи: вставка перед первым элементом списка (т.е. новый элемент становиться первым) и удаление первого элемента списка (т.е. первым становится другой элемент). Поскольку в наших рассуждениях первый элемент считается определяющим узлом всего списка, код для этих случаев потребуется написать отдельно.
Рисунок 3.6. Удаление узла в двухсвязном списке
Вставка:
var
FirstNode, NewNode : PSimpleNode;
begin
• • •
New(NewNode);
.. задать значение поля Data..
NewNode^.Next := FirstNode;
NewNode^.Prior := nil;
FirstNode^.Prior := NewNode;
FirstNode := NewNode;
Удаление:
var
FirstNode, NodeToGo : PSimpleNode;
begin
• • •
NodeToGo := FirstNode;
FirstNode := NodeToGo^.Next;
FirstNode^.Prior := nil;
Dispose(NodeToGo);
