Алгоритм Хаффмана.
Добавлено: 07 апр 2013, 17:41
Всем привет. Пишу архиватор по алгоритму Хаффмана. Пока только работает с текстовыми файлами. Проблема в том что не знаю как сохранить дерево, и как сделать так что бы программа это дерево распознавала. Собственно сам код:
Да и ещё, когда строчка в файле маленькая, ну примерно символов 10, он пробегается по дереву и выводит эту строчку без последнего символа.
Код: Выделить всё
#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();
}