
- •Содержание
- •Рекомендации к проведению лабораторных работ
- •Комментарии в тексте программы
- •Компиляция и запуск программы на выполнение
- •Переменные и константы
- •Операторы и выражения
- •Оператор присваивания
- •Арифметические операции
- •Логические операции
- •Составной оператор begin..end
- •Условный оператор if..then
- •Оператор-селектор case..of
- •Операторы обработки циклов
- •Цикл с параметром for .. do
- •Цикл с предусловием while..do
- •Цикл с постусловием repeat..until
- •Процедуры break и continue
- •Оператор with..do
- •Процедуры и функции
- •Процедуры
- •Функции
- •1. Фундаментальные структуры данных
- •Общее понятие типа данных
- •Простой тип
- •Перечислимые типы данных
- •Поддиапазонны
- •Строковый тип
- •Структурные типы
- •Массивы
- •Записи
- •Множества
- •Представление структур в памяти
- •Задание
- •2. Работа с последовательностями, файлы
- •Доступ к файлу
- •Операции над файлами
- •Окончание файла
- •Пример работы с файлом
- •Задание
- •3. Анализ алгоритмов
- •Рост функций
- •Задание
- •4. Простейшие методы сортировки массивов
- •Оценка алгоритмов сортировки
- •Шейкер-сортировка
- •Сортировка простыми вставками
- •Сортировка бинарными вставками
- •Задание
- •5. Улучшенные методы сортировки массивов
- •Сортировка с помощью включений с уменьшающимися расстояниями (сортировка Шелла)
- •Пирамидальная сортировка
- •Сортировка с разделением (быстрая сортировка)
- •Задание
- •6. Сортировка последовательных файлов
- •Сортировка простым слиянием
- •Естественное слияние
- •Задание
- •7. Рекурсивные алгоритмы
- •Сравнение рекурсии и итерации
- •Задание
- •8. Динамические структуры данных, связные списки
- •Списки
- •Пример создания и заполнения списка
- •Задание
- •9. Нелинейные структуры данных
- •Граф
- •Бинарное дерево
- •Задание
- •10. Алгоритмы на графах
- •Алгоритмы обхода в глубину и по уровням
- •Построение минимального остовного дерева
- •Поиск кратчайшего пути
- •Задание
- •11. Поиск данных
- •Двоичный (бинарный) поиск элемента в массиве
- •Интерполяционный поиск элемента в массиве
- •Алгоритм Бойера-Мура
- •Задание
- •12. Хеширование
- •Отечественный стандарт хеширования
- •Создание хеш-функции
- •Хеш-функции для строковых значений, алгоритм Гонера
- •Задание
- •13. Методы сжатия текстовых данных
- •Метод “Running”
- •Словарные методы сжатия
- •Алгоритм Хаффмана
- •Задание
- •14. Алгоритмы вывода графических примитивов
- •Рисование отрезка
- •Прямое вычисление координат
- •Инкрементный алгоритм Брезенхэма
- •Простейший алгоритм закрашивания замкнутой области
- •Задание
- •15. Псевдослучайные последовательности
- •Метод середин квадратов
- •Линейный конгруэнтный метод
- •Генератор псевдослучайных чисел, поставляемый с системой
- •Оценка качества генератора ПСП
- •Задание
- •16. Параллельные алгоритмы
- •Пример многопоточного приложения
- •Задание
- •Задание на СКР
- •Вариант 1. Клеточные автоматы
- •Вариант 2. Раскрашивание карты
- •Вариант 3. Крисс-кросс
- •Вариант 4. Лабиринт
- •Список использованной литературы
- •Приложение A. Справочник по функциям Delphi
- •Операции с порядковыми типами
- •Математические функции и процедуры
- •Генерация псевдослучайного числа
- •Преобразование типов данных
- •Работа с памятью
- •Приложение Б. Компонент-сетка TStringGrid
- •Приложение В. Компонент-диаграмма TChart
- •Приложение Д. Элементарный поток – класс TThread

61
13.Методы сжатия текстовых данных
Вид занятия – лабораторная работа Цель – исследование методов сокращения избыточности текстовых данных
Продолжительность – 4 часа
Алгоритмы сжатия могут повышать эффективность хранения и передачи данных посредством сокращения их избыточности.
Избыточность в представлении строки S есть L(S) - H(S), где L(S) есть длина представления в битах, а H(S) – энтропия - мера содержания информации, так же выраженная в битах. Алгоритмов, которые могли бы без потери информации сжать строку к меньшему числу бит, чем составляет ее энтропия, не существует.
Метод “Running”
Самый простой из методов упаковки информации называется “Running”. Предположите, что вы имеете строку текста, и в конце строки стоит 40 пробелов. Налицо явная избыточность имеющейся информации. Проблема сжатия этой строки решается очень просто – эти 40 пробелов (40 байт) сжимаются в 3 байта с помощью упаковки их по методу повторяющихся символов. Первый байт, стоящий вместо 40 пробелов в сжатой строке, фактически будет являться пробелом (последовательность была из пробелов). Второй байт – специальный байт "флажка" который указывает что мы должны развернуть предыдущий в строке байт в последовательность при восстановлении строки. Третий байт – байт счета (в нашем случае это будет 40). Как вы сами можете видеть, достаточно чтобы любой раз, когда мы имеем последовательность из более 3-х одинаковых символов, заменять их выше описанной последовательностью, чтобы на выходе получить блок информации меньший по размеру, но допускающий восстановление информации в исходном виде.
Алгоритм Running эффективен только в ситуации, когда мы имеем последовательность из более 3-х повторяющихся символов. В данном методе основной проблемой является выбор того самого байта "флажка", так как в реальных блоках информации как правило используются все 256 вариантов байта и нет возможности иметь 257 вариант - "флажок".
Словарные методы сжатия
Идея словарных методов заключается в замене строк символов на такие коды, что их можно трактовать как индексы какого-то словаря.
Словарь – это набор таких фраз, которые как мы полагаем будут встречаться в обрабатываемой последовательности.
Индексы должны быть построены таким образом, чтобы в среднем их представление составляло меньше места чем требуют замещаемые строки.
Классический представитель словарных методов сжатия данных – алгоритм LZW.
−LZW отказывается от 8-мибитного кодирования и, например, переходит к 10-битному (2^10=1024). Значения кодов 0 - 255 соответствуют отдельным байтам, а коды 256 - 1024 соответствуют подстрокам.
−В процессе кодирования LZW строит таблицу соответствия (словарь) сочетание символов Æ числовое значение.
−Алгоритм LZW приступает к анализу исходной строки преобразуя последовательность сочетаний символов в коды подстрок. Полученные коды заносятся в таблицу соответствия.
Рассмотрим работу алгоритма на примере. Входная строка является кратким списком слов, разделенных символом "/". Указанная строка состоит из 19 символов, что соответствует 19*8=152 битам.

62
Работа начинается с того, что на первом шаге цикла алгоритм выполняет проверку на наличие строки "/W" в таблице словаря (см. табл. 13.1). Когда он не находит эту строку, то генерирует код для "/" и добавляет в таблицу строку "/W". Так как 256 символов уже определены для кодов 0 - 255, то первой определенной строке может быть поставлен в соответствие код 256. После этого система читает следующую букву ("E"), добавляет вторую подстроку ("WE") в таблицу и выводит код для буквы "W".
Таблица 13.1. – Построение словаря для последовательности
Вход |
Выход |
Новые коды и соответст- |
(символы) |
(коды) |
вующие строки |
/W |
/ |
256 = /W |
E |
W |
257 = WE |
D |
E |
258 = ED |
/ |
D |
259 = D/ |
WE |
256 |
260 = /WE |
/ |
E |
261 = E/ |
WEE |
260 |
262 = /WEE |
/W |
261 |
263 = E/W |
EB |
257 |
264 = WEB |
/ |
B |
265 = B/ |
WET |
260 |
266 = /WET |
<EOF> |
T |
|
В результате работы алгоритма мы получаем строку из 12 символов, каждый из которых занимает 10 бит:
Эффект от сжатия данных налицо, исходная строка занимала 152 бита, а сжатая – 120 бит. В результате мы получили выигрыш превышающий 20%.
Теперь познакомимся с алгоритмом распаковки. Алгоритм распаковки получает выходной поток кодов от алгоритма сжатия и использует его для точного восстановления входного потока (см.
табл. 13.2).
Таблица 13.2. – Алгоритм распаковки
Вход |
Старый код |
Выход |
Символ |
Новый вход таблицы |
|
/ |
/ |
/ |
|
|
|
W |
/ |
W |
W |
256 |
= /W |
E |
W |
E |
E |
257 |
= WE |
D |
E |
D |
D |
258 |
= ED |
256 |
D |
/W |
/ |
259 |
= D/ |
E |
256 |
E |
E |
260 |
= /WE |
260 |
E |
/WE |
/ |
261 |
= E/ |
261 |
260 |
E/ |
E |
262 |
= /WEE |
257 |
261 |
WE |
W |
263 |
= E/W |
B |
257 |
B |
B |
264 |
= WEB |
260 |
B |
/WE |
/ |
265 |
= B/ |
T |
260 |
T |
T |
266 |
= /WET |

63
Алгоритм Хаффмана
Алгоритм Хаффмана (англ. Huffman) – жадный алгоритм оптимального префиксного кодирования алфавита с минимальной избыточностью. Этот метод кодирования состоит из двух основных этапов:
1.Построение оптимального кодового дерева.
2.Построение отображения кодÆсимвол на основе построенного дерева.
Допустим, что мы имеем файл длинной в 100 символов и имеющий 6 различных символов в себе, обозначим их как: A, B, C, D, E и F. Мы подсчитали вхождение каждого из символов в файл и получили следующее:
Символ |
C |
E |
B |
F |
A |
D |
Число вхождений |
30 |
25 |
20 |
10 |
10 |
5 |
Процесс формирования оптимального кодового дерева представлен на рисунке 13.1. Символы с наименьшей вероятностью появления (на первом этапе это A и D) объединяют в новый символ, вероятность которого равна суммарной вероятности этих символов. Затем удаляют эти символы и вставляют новый символ в список остальных на соответствующее место (по вероятности).
Далее в дереве находится следующий символ (или пара символов) с наименьшей вероятностью появления. Найденные символы вновь объединяются, и процесс повторяется вновь, до полного построения кодового дерева
Теперь, когда наше дерево создано, мы можем кодировать файл. Мы должны всегда начинать из корня. Кодируя первый символ (лист дерева С) Мы прослеживаем вверх по дереву все повороты ветвей и если мы делаем левый поворот,
Рисунок 13.2. – Кодирование файла
Рисунок 13.1. – Построение оптимального кодового дерева
то запоминаем 0-й бит, и аналогично 1-й бит для правого поворота (рис. 13.2).
После кодирования мы получаем следующие результаты:
-C = 00, занимает 2 бита;
-A = 0100 (4 бита);
-D = 0101 (4 бита);
-F = 011 (3 бита);
-B = 10 (2 бита);
-E = 11 (2 бита).
Эффективность алгоритма Хаффмана весьма высока. Каждый символ изначально представлялся 8-ю битами (один байт), и так как мы уменьшили число битов необходимых для представления каждого символа, мы следовательно уменьшили размер выходного файла. Первоначальный размер файла составлял: 100 байт - 800 бит. Размер сжатого файла: 30 байт - 240 бит, 240 - 30% из 800 , так что мы сжали этот файл на 70%

64
(см. табл. 13.3).
Таблица 13.3. – Анализ результатов кодирования
Частота |
Первоначально |
Уплотненные |
Уменьшено на |
|
|
|
|
биты |
|
C – 30 |
30 x 8 = 240 |
30 x 2 = 60 |
180 |
|
A – 10 |
10 x 8 |
= 80 |
10 x 3 = 30 |
50 |
D – 5 |
5 x 8 = 40 |
5 x 4 = 20 |
20 |
|
F – 10 |
10 x 8 |
= 80 |
10 x 4 = 40 |
40 |
B – 20 |
20 x 8 |
= 160 |
20 x 2 = 40 |
120 |
E – 25 |
25 x 8 |
= 200 |
25 x 2 = 50 |
150 |
Задание
1.На основе метода “Running” разработайте алгоритм упаковки/распаковки произвольной текстовой строки.
2.Используя идею алгоритма “LZW” разработайте функции, кодирующие и декодирующие произвольную текстовую строку. Программа должна позволять выбирать размерность кодирования (в пределах 10-16 бит). Результаты работы программы представьте в табличном виде (см. табл. 13.1 и 13.2).
3.Реализуйте алгоритм Хаффмана кодирования произвольной текстовой строки с алфавитом объёмом до 10 символов. Самостоятельно предложите алгоритм декодирования файла.