Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Теория информации.docx
Скачиваний:
2
Добавлен:
19.09.2019
Размер:
40.78 Кб
Скачать

МИНОБРНАУКИ РОССИИ

Федеральное государственное бюджетное образовательное учреждение

высшего профессионального образования

Ухтинский государственный технический университет

(УГТУ)

КАФЕДРА ИСТ

Контрольная работа:

«Кодирование информации алгоритмом Хаффмана»

Дисциплина

«Теория информации»

Выполнил студент группы ИСТ-1-009 ФБО (к) Серов А. М.

Проверил к.т.н., доцент кафедры ИСТ

Куделин А.Г.

УХТА, 2012

Содержани

Введение 6

Алгоритм построения дерева Хаффмана 8

Листинг программы. 9

// -------------------------------------------------------------------------- 10

#include <vcl.h> 10

#pragma hdrstop 10

#include <string> 10

#include "Hafman.h" 10

// -------------------------------------------------------------------------- 10

#pragma package(smart_init) 10

#pragma resource "*.dfm" 10

TForm1 *Form1; 10

const n=8; 10

struct Character { //Структура: Словарь для подсчёта весов символов 10

char Ch; 10

unsigned int Mas; 10

}; 10

struct Wordbook { //Структура: Итоговый словарь с кодами символов 10

char Ch; 10

char Cd[n]; 10

}; 10

struct TreeAlf { //Структура: Дерево необходимое для определения кодов 10

Character A; //символов 10

TreeAlf *left; 10

TreeAlf *right; 10

}; 10

Wordbook Wordb[256]; //Словарь 11

TreeAlf TreeCod; //Дерево словаря 11

Character Alf[60]; //Промежуточный алфавит 11

int Alength, index; 11

int Mass(char St[], int len) { //Функция подсчёта весов символов 11

int k = 0; 11

for (int i = 0; i < len; i++) { 11

if (St[i] != Alf[0].Ch) { 11

Alf[k].Ch = St[i]; 11

Alf[k].Mas = 0; 11

k++; 11

for (int j = i; j < len; j++) { 11

if (Alf[k - 1].Ch == St[j]) { 11

Alf[k - 1].Mas = Alf[k - 1].Mas + 1; 11

St[j] = Alf[0].Ch; 11

} 11

} 11

} 11

} 11

return k; } 11

void Book(TreeAlf *TreeB, char X, int z) { //Определение кодов символов по 11

if (TreeB->A.Ch == X) { //бинарному дереву 11

Wordb[index].Ch = X; 11

for (int i = z; i < 7; i++) { 11

Wordb[index].Cd[i] = NULL; 11

} 11

} 11

if ((TreeB->left != NULL) && (Wordb[index].Ch != X)) { 11

Wordb[index].Cd[z] = '1'; 11

Book(TreeB->left, X, z+1); 11

} 12

if ((TreeB->right != NULL) && (Wordb[index].Ch != X)) { 12

Wordb[index].Cd[z] = '0'; 12

Book(TreeB->right, X, z+1); 12

} 12

} 12

// -------------------------------------------------------------------------- 12

__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { 12

} 12

// -------------------------------------------------------------------------- 12

AnsiString coder(char St) { //кодирование сообщения 12

AnsiString s; 12

for (int i = 0; i < Alength; i++) { 12

if (Wordb[i].Ch == St) { 12

int j = 0; 12

while ((Wordb[i].Cd[j] == '0') || (Wordb[i].Cd[j] == '1')) { 12

s = s + Wordb[i].Cd[j]; 12

j++; 12

} 12

} 12

} 12

return s; 12

} 12

// -------------------------------------------------------------------------- 12

TreeAlf TrCr[30], *Tr; 12

// -------------------------------------------------------------------------- 12

int Uni(int len) { //функция построения дерева 12

Tr = new TreeAlf; 12

Tr->left = TrCr[len - 1].left; 13

Tr->A.Ch = TrCr[len-1].A.Ch; 13

Tr->right = TrCr[len-1].right; 13

Tr->A.Mas = TrCr[len-1].A.Mas; 13

TrCr[len - 1].left = Tr; 13

TrCr[len - 1].right = &TrCr[len]; 13

TrCr[len - 1].A.Mas = Tr->A.Mas + TrCr[len].A.Mas; 13

TrCr[len - 1].A.Ch = NULL; 13

return len - 1; 13

} 13

int sort(int len) { //Функция сортировки 13

TreeAlf BufferC; 13

for (int i = 0; i < len; i++) { 13

for (int j = len; j > i; j--) { 13

if (TrCr[j].A.Mas > TrCr[j - 1].A.Mas) { 13

BufferC = TrCr[j - 1]; 13

TrCr[j - 1] = TrCr[j]; 13

TrCr[j] = BufferC; 13

} 13

} 13

} 13

return len; 13

} 13

// -------------------------------------------------------------------------- 13

void __fastcall TForm1::TreeCrClick(TObject *Sender) { 13

AnsiString Temp = Text1->Text; 13

char *Text = Temp.c_str(); 13

Alength = Mass(Text, strlen(Text)); 13

int Al = Alength; 13

for (int i = 0; i <= Al; i++) { 13

TrCr[i].A = Alf[i]; 13

TrCr[i].left = NULL; 14

TrCr[i].right = NULL; 14

} 14

while (Al != 1) { 14

Al = sort(Al); 14

Al = Uni(Al); 14

} 14

TreeCod.left = &TrCr[0]; 14

TreeCod.right = &TrCr[1]; 14

TreeCod.A.Mas = TrCr[0].A.Mas + TrCr[1].A.Mas; 14

TreeCod.A.Ch = NULL; 14

for (index = 0; index < Alength; index++) { 14

Book(&TreeCod, Alf[index].Ch, 0); 14

} 14

for (int i; i < index; i++) { 14

} 14

Temp = Text1->Text; 14

Text = Temp.c_str(); 14

for (unsigned int i = 0; i < strlen(Text); i++) { 14

Final->Text = Final->Text + coder(Text[i]); 14

} 14

} 14

// -------------------------------------------------------------------------- 14

Библиографический список 16

Введение 3

Алгоритм построения дерева Хаффмана 5

Листинг программы. 7

Заключение 12

Библиографический список 11

Введение

Один из первых алгоритмов эффективного кодирования информации был предложен Д. А. Хаффманом в 1952 году. Идея алгоритма состоит в следующем: зная вероятности вхождения символов в сообщение, можно описать процедуру построения кодов переменной длины, состоящих из целого количества битов. Символам с большей вероятностью присваиваются более короткие коды. Коды Хаффмана имеют уникальный префикс, что и позволяет однозначно их декодировать, несмотря на их переменную длину.

Классический алгоритм Хаффмана на входе получает таблицу частот встречаемости символов в сообщении. Далее на основании этой таблицы строится дерево кодирования Хаффмана (Н-дерево). Алгоритм построения Н-дерева прост и элегантен.

Символы входного алфавита образуют список свободных узлов. Каждый лист имеет вес, который может быть равен либо вероятности, либо количеству вхождений символа в сжимаемое сообщение.

Выбираются два свободных узла дерева с наименьшими весами.

Создается их родитель с весом, равным их суммарному весу.

Родитель добавляется в список свободных узлов, а двое его детей удаляются из этого списка.

Одной дуге, выходящей из родителя, ставится в соответствие бит 1, другой —бит 0.

Шаги, начиная со второго, повторяются до тех пор, пока в списке свободных узлов не останется только один свободный узел. Он и будет считаться корнем дерева.

Допустим, у нас есть следующая таблица частот:

15 7 6 6 5

А Б В Г Д

Этот процесс можно представить как построение дерева, корень которого — символ с суммой вероятностей объединенных символов, получившийся при объединении символов из последнего шага, его n0 потомков — символы из предыдущего шага и т. д.

Чтобы определить код для каждого из символов, входящих в сообщение, мы должны пройти путь от листа дерева, соответствующего этому символу, до корня дерева, накапливая биты при перемещении по ветвям дерева. Полученная таким образом последовательность битов является кодом данного символа, записанным в обратном порядке.

Для данной таблицы символов коды Хаффмана будут выглядеть следующим образом.

А Б В Г Д

0 100 101 110 111

Поскольку ни один из полученных кодов не является префиксом другого, они могут быть однозначно декодированы при чтений их из потока. Кроме того, наиболее частый символ сообщения А закодирован наименьшим количеством битов, а наиболее редкий символ Д — наибольшим.

Классический алгоритм Хаффмана имеет один существенный недостаток. Для восстановления содержимого сжатого сообщения декодер должен знать таблицу частот, которой пользовался кодер. Следовательно, длина сжатого сообщения увеличивается на длину таблицы частот, которая должна посылаться впереди данных, что может свести на нет все усилия по сжатию сообщения. Кроме того, необходимость наличия полной частотной статистики перед началом собственно кодирования требует двух проходов по сообщению: одного для построения модели сообщения (таблицы частот и Н-дерева), другого для собственно кодирования.

Алгоритм построения дерева Хаффмана

Символы входного алфавита образуют список свободных узлов. Каждый лист имеет вес, который может быть равен либо вероятности, либо количеству вхождений символа в сжимаемое сообщение;

Выбираются два свободных узла дерева с наименьшими весами;

Создается их родитель с весом, равным их суммарному весу;

Родитель добавляется в список свободных узлов, а двое его детей удаляются из этого списка;

Одной дуге, выходящей из родителя, ставится в соответствие бит 1, другой – бит 0;

Шаги, начиная со второго, повторяются до тех пор, пока в списке свободных узлов не останется только один свободный узел. Он и будет считаться корнем дерева.

Окно Программы: