Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум «Всё о Паскале» _ Задачи _ Алгоритм Хаффмана

Автор: Pistoletka 6.11.2016 1:35

Здравствуйте, я сейчас пишу программу по алгоритму Хаффмана и столкнулась с проблемой: при кодировании, если ввожу такую строку "kkkkkkk", то по идее должно выдавать ошибку о том, что дерево не может быть создано. Подскажите, пожалуйста, как сделать проверку на такой случай, когда мы вводим только одну букву несколько раз?
Вот моя процедура кодирования:

Procedure shifr();
var i, n:integer;
begin
writeln('Введите текст: ');
readln(s);
for i := 0 to 255 do //Инициализация массива(счетчика)
mass[i] := 0;
for i := 1 to length(s) do //подсчет числа символов
inc(mass[ord(s[i])]);//выдает код i-того символа
n := 0;
for i := 0 to 255 do
if mass[i] <> 0 then begin//Формируем листья дерева
inc(n);
new(TMass[n]);
TMass[n]^.N := Mass[i];
TMass[n]^.symbol := chr(i);
TMass[n]^.Left := nil;
TMass[n]^.Right := nil;
end;
Sort(TMass, N);

//Формируем само дерево
while n > 1 do
begin
new(p);
p^.n := TMass[n]^.N + TMass[n - 1]^.N;
p^.left := TMass[n - 1];
p^.right := TMass[n];
TMass[n - 1] := p;
Dec(n); //Уменьшает значение n на 1
Sort(TMass, N);
end;

//Подсчитываем число бит для закодированного текста
n:=0;
for i:=0 to 255 do
if mass[i]<>0 then
n:=n+mass[i]*length(GetCode(p, chr(i), ''));
Writeln('Число бит закодированного текста: ',n);

g := ''; //Кодируем строку
for i := 1 to length(s) do
begin
g:=g+GetCode(p, s[i], '');
end;
Writeln('Закодированный текст: ', g);
end;

Автор: Федосеев Павел 6.11.2016 15:49

А почему нельзя создавать дерево?

Автор: Pistoletka 6.11.2016 16:25

Цитата(Федосеев Павел @ 6.11.2016 11:49) *

А почему нельзя создавать дерево?

А как оно может быть создать из одного символа? Ему же двигаться негде. Просто без проверки я вводила "kkkkk", и выводило такую ошибку: Ошибка времени выполнения: Ссылка на объект не указывает на экземпляр объекта.
function GetCode(T: PTree; C: char; path: string): string;// Возвращает код Хоффманa
begin
if (T^.Left=nil) and (T^.Right=nil) and (T^.symbol=C) then
result:=path
else
begin
result:='';
if T^.left <> nil then
result := GetCode(t^.left, C, path + '0');
if (result='') and (T^.right <> nil) then
result := GetCode(t^.right, C, path + '1');
end;
end;

Ошибка вылезает на этой строке
 if (T^.Left=nil) and (T^.Right=nil) and (T^.symbol=C) then

Автор: Федосеев Павел 6.11.2016 21:43

Но архиваторы же сжимают такие строки?
Значит этот символ с избытком кодируется одним битом.

Автор: OCTAGRAM 7.11.2016 10:21

По логике алгоритма, если на входе лист (Left и Right не присвоены), а символ в листе отличается от символа в аргументе, надо выходить с пустым результатом, а вместо этого исполнение заходит в else

Автор: Pistoletka 8.11.2016 0:24

Цитата(OCTAGRAM @ 7.11.2016 6:21) *

По логике алгоритма, если на входе лист (Left и Right не присвоены), а символ в листе отличается от символа в аргументе, надо выходить с пустым результатом, а вместо этого исполнение заходит в else

Спасибо за ответ, но я уже справилась со своей проблемой! smile.gif