Модераторы: bsa
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Код Хафмена. Не могу найти ошибку, энтропия, средняя длина кода сжатия 
:(
    Опции темы
Асоишница
Дата 27.2.2013, 22:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 45
Регистрация: 13.3.2012

Репутация: нет
Всего: нет



Было 6 файлов: .txt , .doc , .docx , .bmp , .jpg , .rar
Составила таблицу частот встречаемости символов и посчитала энтропию. Затем в отдельной проге(таково условие) ссчитала с файла частоты и закодировала символы методом Хафмена. Проблема вот в чём. Средняя длина не должна быть меньше энтропии. Энтропия- это минимальная величина сжатия, а длина кодов должна быть больше, причём у текстовых не намного, а много на архивных, несжатых графич(bmp).....Так вот на большом текстовом разница аж в 0,2!!! ......хотя относительно друг друга всё правильно: min у текстовых max у архивных(вот только .doc странно себя ведёт- по идее должен обладать стпенью сжатия почти как txt, а средняя длина больше энтропии, хотя даже rar и bmp меньше). В текстовом из 3-х слов всё хорошо. и считает правильно- проверено отладчиком и сравнила вручную..... есть примерные результаты файлов, которые должны получиться. там всё как надо.......но коды символов не совсем совпадают- пару штук меньшей или большей длины, чем надо. (Длина- количество 0 и 1(001- длина 3, 10- длина 2)).


Вот код
Код

#include <stdio.h>
#include <conio.h>
#include <math.h>
#include <locale.h>
#include <stdlib.h>
#include <string.h>
 
struct sym //структуры или записи
{
        float ch;
        double freq; 
        char code[255];
        sym *left;
        sym *right;
};
 
 
sym *makeTree(sym *psym[],int k)//рeкурсивная функция создания дерева Хaфмана
{
    sym *temp;
    temp=(sym*)malloc(sizeof(sym));
    temp->freq=psym[k-1]->freq+psym[k-2]->freq;
    temp->code[0]=0;
    temp->left=psym[k-1];
    temp->right=psym[k-2];
 
    if(k==2)
        return temp;
    else //внесение в массив в нужное место элемента дерева Хафмана
    {
        for(int i=0;i<k;i++)
            if (temp->freq>psym[i]->freq)
            {   
                for(int j=k-1;j>i;j--)
                    psym[j]=psym[j-1];                                  
                
                psym[i]=temp;
                break;
            }       
    }
return makeTree(psym,k-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 ()
{
    setlocale(LC_ALL, "Russian");
        
    int k=0; //счётчик количества различных букв, уникальных символов
    sym simbols[256]={0}; //инициализируем массив записей 
    sym *psym[256]; //инициализируем массив указателей на записи
    char IN[100], OUT[100], name[15], siz[15], str[40], *leks;
    double mas[2][256]={0}, ent, len=0;
    int size, i=0, j=0;
    FILE *f, *fp2;
    
    printf("Введите путь к исследуемому файлу:\n");
    scanf("%s", IN);
    printf("Введите путь к конечному файлу:\n");
    scanf("%s", OUT);
    fp2=fopen(OUT,"wt");//открываем файл для записи бинарного кода

    if((f=fopen(IN, "rb"))==NULL)
    {
        printf("Файл не может быть открыт.\n");
        exit(1);
    }

    fgets(name, 20, f);                //Считываем имя
    fgets(siz, 20, f);                //Считываем размер
    sscanf(siz, "%d", &size);        //Конвертируем размер

    fgets(str, 40, f);                //Считываем пустую строку

    int fl=0;
    while(fl==0)                    //Выполнять пока не встретим пустую строку
    {
        fgets(str, 40, f);
        
        if(strcmp(str, "\r\n")!=0)    //Встретили ли пустую строку?
        {
            k++;
            leks=strtok(str," \t");    //Считывание кода
            mas[0][i]=atof(leks);
            
            leks=strtok(NULL," \t");    //Считывание вероятности
            mas[1][i]=atof(leks);
            i++;
        }
        else
            fl=1;                    //Встретили пустую строку, установить флаг
    }

    fgets(str, 40, f);                //Считываем строку с энтропией
    
    leks=strtok(str, ":");        
    leks=strtok(NULL, ":");            //Отделяем число энтропии (вторая лексема)
    ent=atof(leks);
   
    
    sym *symbols=(sym*)malloc(k*sizeof(sym));//создание динамического массива структур simbols
    sym **psum=(sym**)malloc(k*sizeof(sym*));//создание динамического массива указателей на simbols
 
    // Фиксируем частоты встречаемости
    for(int i=0;i<k;i++){
        simbols[i].ch=mas[0][i];
        simbols[i].freq=mas[1][i];}
    
    for(int i=0;i<k;i++) //в массив указателей заносим адреса записей
        psym[i]=&simbols[i];
 
    
    sym *root=makeTree(psym,k);//вызов функции создания дерева Хафмана
    
    makeCodes(root);//вызов функции получения кода
 
  rewind(f);//возвращаем указатель в файле в начало файла
//записываем полученные в функциях коды в файл

        fprintf(fp2,"%s%d\n\n", name, size);
        for(i=0;mas[1][i]>0;i++){
    if(mas[0][i]<10)
        fprintf(fp2,"%.0f  \t%s\n",mas[0][i],simbols[i].code);
    if(mas[0][i]>10 && mas[0][i]<100)
        fprintf(fp2,"%.0f \t%s\n",mas[0][i],simbols[i].code);
    if(mas[0][i]>100)
    fprintf(fp2,"%.0f\t%s\n",mas[0][i],simbols[i].code);}
    //fputs(simbols[i].code,fp2);
        for(int i=0;i<k;i++)
            len+= ((int)strlen(simbols[i].code))*simbols[i].freq;

    fprintf(fp2,"\r\n%s%.*f", "Средняя длина кода сжатия: ", 10, len);
    fprintf(fp2,"\r\n%s%.*f", "                 Энтропия: ", 10, ent);

 
fcloseall();//закрываем все открытые файлы

return 0;
 getch();
 }




Среда: VS2010

В прикреплённом файле правильные и неправильные результаты+ в правильных код на паскале, с помощью которого знаю правильные. Но в паскале я не бум-бум, просто попросила обработать готовый код, а то у меня даже инсталятора его нет.


Это сообщение отредактировал(а) Асоишница - 27.2.2013, 22:37

Присоединённый файл ( Кол-во скачиваний: 1 )
Присоединённый файл  файлы.rar 35,85 Kb
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

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


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0471 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.