Страница 1 из 1

Алгоритм Хаффмана.

Добавлено: 07 апр 2013, 17:41
Frairs
Всем привет. Пишу архиватор по алгоритму Хаффмана. Пока только работает с текстовыми файлами. Проблема в том что не знаю как сохранить дерево, и как сделать так что бы программа это дерево распознавала. Собственно сам код:

Код: Выделить всё

#include <iostream>
#include <vector>
#include <list>
#include <map>
#include <stdio.h>
#include <fstream>
using namespace std;
class Node {
    public:
    int a;
    char c;
    Node *left, *right;
    Node (){};
    Node (Node *L, Node *R)
    {
        left = L;
        right = R;
        a=L->a+R->a;
    }
};

struct MyCompare
{
    bool operator()(Node* l, Node* r) const //перегрузка оператора
    {
        return l->a < r->a;
    }
};

vector <bool> code;
map <char, vector<bool> > table; //символ и ему присвоеный код
map <char, vector<bool> >::iterator itrCode;


void BuildTable (Node *root) //присваиваем символу код
{

    if (root->left!=NULL)
    {
        code.push_back(0);
        BuildTable (root->left);
    }

    if (root->right!=NULL)
    {
        code.push_back(1);
        BuildTable (root->right);
    }

    if (root->c)
    {
        table[root->c]=code;
    }
    code.pop_back();


}
void print (Node* root, unsigned k=0) //вывод дерева, это для проверки программы
{
    if (root!=NULL)
    {
        print (root->left, k+3);

        for (unsigned i=0; i<k; i++)
        {
            cout << "   ";
        }

        if (root->c) cout << root->a << " (" << root->c << ") " << endl;
        else cout << root->a <<endl;
        print(root->right, k+3);
    }
}
int main(int argc, char *argv[])
{
string s;

ifstream f;
f.open("1.txt");
ofstream g;
g.open ("2.bin");
map <char, int> m; //тут символ и сколько раз он использован

int count=0; char buf=0;
while (!f.eof()) //считываем символы в файле
{
    char c;
    c=f.get();
    m[c]++;

}

map <char, int>::iterator itr;
list<Node*> t;
for (itr=m.begin(); itr!=m.end(); itr++) //считываем с мап и записываем в лист.
{
    Node *p=new Node;

    p->c=itr->first;
    p->a=itr->second;

    t.push_back(p);

}

while (t.size()!=1) //запись кода соответствующего символа.
   {
    t.sort (MyCompare());

    Node *SonL=t.front();
    t.pop_front();

    Node *SonR=t.front();
    t.pop_front();
    Node *parent = new Node(SonL, SonR);
    t.push_back(parent);
    }


   Node *root=t.front();
//unsigned k=0;
// print (root, k);

 BuildTable (root); //в этой функции присваиваем символу код

f.clear(); f.seekg(0);
while (!f.eof()) //записываем код в двоичный фаил.
{
      char c;
      c=f.get();
      vector<bool> x = table[c];
        for (int n=0; n<x.size(); n++)
        {
            buf = buf | x[n]<< (7-count);
            count++;
            if (count==8) {count=0; g<<buf; buf=0;}
        }

}
f.close();
g.close();


ifstream F;
F.open("2.bin");
ofstream V;
V.open ("3.txt");
Node *p=root;
count=0;
char byte;
F>>byte;

while (!F.eof()) //вывожу текст по дереву на консоль и в фаил
{
    bool b=byte & (1<<(7-count));
    if (b) p=p->right;
    else p=p->left;
    if (p->left==NULL && p->right==NULL)
        {
            cout << p->c;
            V << p->c;
            p=root;
        }

    count++;
    if (count==8){count=0; F>>byte;;}
}

F.close();
}
Да и ещё, когда строчка в файле маленькая, ну примерно символов 10, он пробегается по дереву и выводит эту строчку без последнего символа.

Re: Алгоритм Хаффмана.

Добавлено: 09 апр 2013, 15:52
Ne0N
не всматривался в код (да и меня раздражают плюсы), но по закону жанра для статического хаффмана в выходной файл сохраняется собранная статистика, ну и естественно сама кодированная последовательность. Статистика у тебя по ходу в m хранится.