- •Что я должен предварительно знать?
- •Какая версия 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 двух файлов
- •Список литературы
Отладка
При разработке приложений всегда наступает момент, когда приходится переходить к поиску и устранению ошибок. В настоящей книге мы не будем подробно описывать процесс отладки, давать советы по использованию отладчика и описывать методы поиска и устранения основных типов ошибок. Здесь будут приведены лишь основные правила, которые позволят читателю существенно упростить сам процесс отладки. Все они взяты из книги Роббинса (Robbins) [19].
‑‑‑‑
Правило отладки № 1. Выбирайте воспроизводимый случай тестирования.
‑‑‑‑
По нечеткому описанию проблемы можно обнаружить только самые простые ошибки. Тестовый случай, который при необходимости может воспроизвести ошибку, ‑ это, по крайней мере, 90% на пути к ее обнаружению и устранению. Возможность воспроизведения ошибки позволяет с помощью отладчика определить место, где она возникает. Если же у вас нет теста, который может воспроизвести ошибку, то у вас нет и надежды.
Второе правило отладки намного сложнее.
‑‑‑‑
Правило отладки № 2. Исходите из того, что ошибка внесена вами.
‑‑‑‑
Может быть, вы неправильно используете API‑интерфейс операционной системы или библиотека компонентов требует определенной последовательности операций. Или, в конце концов, может быть, вызываемая вами функция не может принимать nil в каком‑либо входном параметре. Маловероятно, чтобы ошибка была вызвана неправильной работой API‑интерфейса или компилятора. Более вероятно, что ошибка присутствует в библиотеке компонентов, тем не менее, попытайтесь выделить проблему (см. правило отладки 1), что позволит с уверенностью сказать, что ошибка находится не в вашем коде. Конечно, если ошибка находится не в вашем коде, ваша задача только усложняется, поскольку придется положиться на разработчиков операционной системы, компилятора или библиотеки компонентов, что они достаточно быстро устранят имеющуюся проблему.
Следующее правило вытекает из уже рассмотренного нами материала.
‑‑‑‑
Правило отладки № 3. Для проверки того, что код работает, как того ожидалось, используйте утверждения.
‑‑‑‑
Кроме того, можно применять и протоколирование, которое позволит отслеживать состояние различных объектов.
А теперь перейдем собственно к отладке.
‑‑‑‑
Правило отладки № 4. Используйте автоматизированные инструментальные средства отладки.
‑‑‑‑
Возможно, ваша ошибка вызвана перезаписью какой‑то области памяти или получением доступа к памяти после того, как она была освобождена, либо, скажем, при вызове API‑функции не проверяется код возвращаемой ошибки. Все описанные типы проблем можно обнаружить в таком автоматизированном средстве отладки, как TurboPower Sleuth QA Suite. Приобретите средство отладки и используйте его не только в процессе тестирования, но и в процессе обнаружения ошибок.
Естественно, после этого следует сама отладка, которая может выполняться даже с помощью отладчика. Именно здесь наука программирования превращается в настоящее искусство. Отладку нельзя назвать алгоритмом, скорее, это соревнование. Единственным советом в этом соревновании может быть "не делайте никаких допущений". Если вы считаете, что некоторая переменная должна содержать определенное значение, проверьте это. Пользуйтесь средством визуализации значений отладчика. Для наблюдения за блоком памяти можно воспользоваться окном процессора. Попытайтесь предсказать значения переменных, а затем проверить свои предположения и при необходимости устраните ошибки. Без боязни добавляйте в код новые утверждения с целью проверки своих предположений.
Резюме
Эта глава была достаточно насыщена информацией и, честно говоря, была посвящена не столько алгоритмам и структурам данных, сколько технологиям увеличения быстродействия кода и процедурным методам.
Иногда быстродействие является результатом правильного выбора алгоритма или структуры данных (или того и другого). В других случаях увеличение скорости может быть достигнуто благодаря глубоким знаниям оборудования компьютера и операционной системы. Прежде всего, важно понимать, что единственным методом увеличения быстродействия приложения является использование профилировщика. Только предоставляемая профилировщиком статистика поможет определить, на что приложение тратит время, и лишь глубокое изучение отдельных блоков кода позволит оптимизировать приложение и увеличить его быстродействие. Хотелось бы подчеркнуть, что просто выбор "правильного" алгоритма или структуры данных отнюдь не означает, что приложение будет работать быстрее. Приведенная в книге информация поможет вам понять возможные способы ускорения выполнения отдельных частей кода, но только не нужно вносить в код сложные реализации алгоритмов там, где этого не требуется ‑ вы только зря потеряете время.
Кроме того, в этой главе мы кратко рассмотрели тестирование и отладку ‑ это тоже не алгоритмы, а скорее методы, гарантирующие, что код не содержит ошибок. А если ошибки все‑таки присутствуют, то в коде находится столько разного рода следов и указателей, что поиск и устранение ошибок не должны отнимать много времени.
