Страница 1 из 2
Ошибка в кодах хаффмана
Добавлено: 20 сен 2009, 18:30
Sobakaa
Код: Выделить всё
#include<stdio.h>
#include<stdlib.h>
#include <string.h>
#define SIZE 256
struct SYM
{
unsigned char ch; //ascii
float freq; //symbol frequency
char code[SIZE]; //new huffman code
SYM *left; //left hand of tree
SYM *right; //right hand of tree
};
SYM* huffTree(SYM *syms[], int N) //array of SYM structs and size N
{
SYM *temp=(SYM*)malloc(sizeof(SYM));
temp->freq=syms[N-1]->freq+syms[N-2]->freq;
temp->code[0]=0;
temp->left=0;
temp->right=0;
temp->left=syms[N-2];
temp->right=syms[N-1];
if(N==2)
return temp;
else
{
for(int i=0;i<N;i++)
{
if(temp->freq>syms[i]->freq)
{
syms[N-1]=syms[i];
syms[i]=temp;
temp=syms[N-1];
}
}
return huffTree(syms, N-1);
}
}
void makeCodes(SYM *root)
{
if (root->left)
{
strcpy(root->left->code,root->code);
strcat(root->left->code,"0");
makeCodes(root->left);
}
if (root->right)
{
strcpy(root->right->code,root->code);
strcat(root->right->code,"1");
makeCodes(root->right);
}
}
int main()
{
int i=5;
SYM *syms[SIZE];
SYM arr[SIZE];
arr[0].ch='a';
arr[0].freq=0.4;
arr[1].ch='b';
arr[1].freq=0.3;
arr[2].ch='c';
arr[2].freq=0.1;
arr[3].ch='d';
arr[3].freq=0.1;
arr[4].ch='e';
arr[4].freq=0.1;
syms[0]=&arr[0];
syms[1]=&arr[1];
syms[2]=&arr[2];
syms[3]=&arr[3];
syms[4]=&arr[4];
SYM* root=huffTree(syms, i);
makeCodes(root);
}
Не могу понять, в чём ошибка. Отладчик вылетает при первом обращении к strcpy, помещая в корень букву b.
Re: Ошибка в кодах хаффмана
Добавлено: 20 сен 2009, 19:15
_SG
а как память под *syms[SIZE] выделяется?
Re: Ошибка в кодах хаффмана
Добавлено: 20 сен 2009, 19:49
Sobakaa
а как память под *syms[SIZE] выделяется?
Так это, статически. Под структурки в первой функции.
Не работает именно создание кодов.
Re: Ошибка в кодах хаффмана
Добавлено: 20 сен 2009, 20:22
_SG
Статически? Я вижу лишь указатель на массив. А где под сам массив память выделяется? Я действительно не понимаю( Я не великий эксперт и просто не понимаю, что в итоге попадает в huffTree.
Re: Ошибка в кодах хаффмана
Добавлено: 20 сен 2009, 20:56
Sobakaa
Ммм, это массив указателей на структуру. Т.е. стоит читать SYM *syms[SIZE]. если по анси, то было бы
struct SYM *syms[SIZE].
В обращении же к левым-правым ветвям не знаю что происходит - не силён в структурах.
Re: Ошибка в кодах хаффмана
Добавлено: 20 сен 2009, 22:41
_SG
Тьфу! Даже это забыл(
Re: Ошибка в кодах хаффмана
Добавлено: 21 сен 2009, 01:53
L.A.V.
А происходит следующее:
На третьей рекурсии функции makeCodes() условие
срабатывает не так как того хотелось бы, от того что root->left содержит указатель на мусор, а не нулевой адрес. А то что не ноль - все правда

Далее функция strcpy() обращается к неинециализированному или недоступному участку памяти, что ни к чему хорошому не приводит.
Решение проблемы:
ограничить все висячие вершины дерева нулевыми указателями.
Сделать это нужно при посторении дерева, как я понимаю в huffTree().
Это относительно того, что ты спрашивал, а вобще не совсем уверен что дерево строится правильно, хотя могу ошибаться, особо в алгоритме не разбирался.
Re: Ошибка в кодах хаффмана
Добавлено: 21 сен 2009, 12:23
Sobakaa
Господа, вы не поверите - стоило мне воспользоваться режимом совместимости с предыдущей версией вижуал студио, с которой я перенёс исходник, как оно заработало!
>_< i'm going to Redmond and i'm going to kill!
Спасибо за советы, теперь лишних связей в дереве нет.
Re: Ошибка в кодах хаффмана
Добавлено: 21 сен 2009, 15:22
L.A.V.
Ну вот, а я как раз разобрался в алгоритме и даже нашел багу.
Но на счет зануления все же напишу, мож пригодится.
В момент инициализации массива буквами и вероятностями можно сделать следующее.
Код: Выделить всё
int main()
{
...
arr[4].ch='e';
arr[4].freq=0.1;
for(int i = 0; i < SIZE; ++i)
{
arr[i].left = 0;
arr[i].right = 0;
}
syms[0]=&arr[0];
syms[1]=&arr[1];
...
}
после этого тоже все работает. Безо всяких переключений совместимости.

Теперь на счет бага.
Само дерево строится в принципе правильно, но с одним минусом - буква 'c' теряется, в место этого появляютя две буквы 'd'.
По моему все дело в сортировкое в haffTree().
Re: Ошибка в кодах хаффмана
Добавлено: 22 сен 2009, 13:19
Sobakaa
Ага, за зануление спасибо. В принципе штука не необходимая, но мусора нет - нет и опасности его куда-нибудь записать. Да и аксесс виолэйшн, который раньше один раз на 10 появлялся, кажется, пропал.
Что касается баги - у себя повторить не смог. Все символы файла в дереве, всё как надо. Возможно я выложил сюда код с багом, там пузырёк был так себе, я его переписал.