哈夫曼编码
哈夫曼编码加压缩,解压
// HuffmanTree.h
// HuffmanTree.h
#ifndef HUFFMANTREE_H
#define HUFFMANTREE_H
#include<bits/stdc++.h>
using namespace std;
typedef struct Hufnode
{
int rt,lchild,rchild,w;
}Hufnode,*Huftree;
class HuffmanTree
{
public:
void CreatHuf(int n,int *word);
public:
Hufnode *Hfm;
int num,tot; //
};
#endif // HUFFMANTREE_H
// HuffmanTree.cpp
// HuffmanTree.cpp
#include "HuffmanTree.h"
#include<bits/stdc++.h>
using namespace std;
//typedef pair<int,int>pair<int,int>;
void HuffmanTree::CreatHuf(int n,int *word)
{
num=n;
tot=2*num-1;
Hfm=new Hufnode[tot+1];
for(int i=1;i<=tot;i++) // 完全初始化
{
Hfm[i].w=0;
Hfm[i].rt=0;
Hfm[i].lchild=0;
Hfm[i].rchild=0;
}
priority_queue< pair<int,int>,vector< pair<int,int> >,greater< pair<int,int> > > que; //优先队列返回最小值
for(int i=1;i<=n;i++)
{
Hfm[i].w=word[i];
que.push(make_pair(Hfm[i].w,i));
}
for(int i=n+1;i<=tot;i++)
{
int min_1,min_2;
min_1=que.top().second;
que.pop();
min_2=que.top().second;
que.pop();
Hfm[i].lchild=min_1;
Hfm[i].rchild=min_2;
Hfm[min_1].rt=i;
Hfm[min_2].rt=i;
Hfm[i].w=Hfm[min_1].w+Hfm[min_2].w;
que.push(make_pair(Hfm[i].w,i));
}
}
// main.cpp
// main.cpp
#include<bits/stdc++.h>
#include<windows.h>
#include "HuffmanTree.h"
using namespace std;
typedef char **HuffmanCode; //哈夫曼编码表
int word[300];
HuffmanCode HC;
map<char,int> mp;// 字母对应编号
map<int,char> decmp; // 编号对应字母
void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,int n) // 哈夫曼编码
{
HC=(HuffmanCode)malloc((n+1)*sizeof(char *));
char *cd=new char [n];
cd[n-1]='\0';
for(int i=1;i<=n;i++)
{
int start=n-1;
for(int j=i,fa=HT.Hfm[i].rt;fa!=0;j=fa,fa=HT.Hfm[fa].rt)
{
if(HT.Hfm[fa].lchild==j) cd[--start]='0';
else cd[--start]='1';
}
HC[i]=(char*)malloc((n-start)*sizeof(char));
strcpy(HC[i],&cd[start]);
}
delete cd;
}
void Menu_Show()
{
cout<<"**********************************************************************"<<endl;
cout<<"* 哈夫曼编码译码器 *"<<endl;
cout<<"* 1、选择需要进行编码的文件 *"<<endl;
cout<<"* 2、建立哈夫曼树 *"<<endl;
cout<<"* 3、建立密码本并对文件编码 *"<<endl;
cout<<"* 4、选择需要进行解码的文件并解码 *"<<endl;
cout<<"* 5、按位压缩方式对文件进行压缩 *"<<endl;
cout<<"* 6、对压缩的文件进行解压 *"<<endl;
cout<<"* 7、对解压缩的文件进行解码 *"<<endl;
cout<<"* 输入其他任意数字退出 *"<<endl;
cout<<"**********************************************************************"<<endl;
}
void Option_1(int &n)
{
DWORD startTime=GetTickCount();
ofstream out("D:\\C,C++\\数据结构\\HuffmanCode\\计时.txt");
char c;
ifstream in("D:\\C,C++\\数据结构\\HuffmanCode\\原文.txt");
mp.clear();
int tot=0;
while(in.get(c))
{
if(mp[c]==0)
mp[c]=(++tot),decmp[tot]=c;
word[mp[c]]++;
}
cout<<" 编码的文件读入成功"<<endl;
n=tot;
in.close();
DWORD endTime=GetTickCount();
out<<"读入要编码的文件运行时间为::"<<endTime-startTime<<"ms"<<endl;
}
void Option_2(HuffmanTree&hf,int n)
{
DWORD startTime=GetTickCount();
ofstream out("D:\\C,C++\\数据结构\\HuffmanCode\\计时.txt",ios::app);
hf.CreatHuf(n,word);
cout<<" 哈夫曼树已成功建立"<<endl;
cout<<" ***哈夫曼树如下***\n"<<endl;
cout<<"编号 权 值 父节点 左子节点 右子节点\n";
for(int i=1;i<=hf.tot;i++)
{
printf("%4d %4d %4d %4d %4d\n",i,hf.Hfm[i].w,hf.Hfm[i].rt,hf.Hfm[i].lchild,hf.Hfm[i].rchild);
}
DWORD endTime=GetTickCount();
out<<"建立哈夫曼树并输出哈夫曼树运行时间为::"<<endTime-startTime<<"ms"<<endl;
}
void Option_3(HuffmanTree hf,int n)
{
DWORD startTime=GetTickCount();
ofstream outf("D:\\C,C++\\数据结构\\HuffmanCode\\计时.txt",ios::app);
HuffmanCoding(hf,HC,n);
ofstream out("D:\\C,C++\\数据结构\\HuffmanCode\\哈夫曼编码文.txt");
cout<<" 密码本已成功建立 "<<endl;
cout<<" ***如下*** "<<endl;
for(int i=1;i<=n;i++)
{
if(decmp[i]=='\n') cout<<"Enter";
else cout<<decmp[i];
cout<<" :";
cout<<HC[i]<<endl;
}
char c;
ifstream in("D:\\C,C++\\数据结构\\HuffmanCode\\原文.txt");
while(in.get(c))
{
out<<HC[mp[c]];
}
out.close();
in.close();
DWORD endTime=GetTickCount();
outf<<"建立密码本并编码运行时间为::"<<endTime-startTime<<"ms"<<endl;
}
void Option_4(HuffmanTree hf,int n)
{
DWORD startTime=GetTickCount();
ofstream outf("D:\\C,C++\\数据结构\\HuffmanCode\\计时.txt",ios::app);
ifstream in("D:\\C,C++\\数据结构\\HuffmanCode\\哈夫曼编码文.txt");
ofstream out("D:\\C,C++\\数据结构\\HuffmanCode\\哈夫曼解码文.txt");
int now=2*n-1;
char c;
while(in.get(c))
{
if(c=='1') now=hf.Hfm[now].rchild;
else now=hf.Hfm[now].lchild;
if(hf.Hfm[now].rchild==0 && hf.Hfm[now].lchild==0)
{
out<<decmp[now];
now=2*n-1;
}
}
in.close();
out.close();
DWORD endTime=GetTickCount();
outf<<"解码哈夫曼编码文运行时间为::"<<endTime-startTime<<"ms"<<endl;
}
void Option_5()
{
DWORD startTime=GetTickCount();
ofstream outf("D:\\C,C++\\数据结构\\HuffmanCode\\计时.txt",ios::app);
ifstream in("D:\\C,C++\\数据结构\\HuffmanCode\\哈夫曼编码文.txt");
ofstream out("D:\\C,C++\\数据结构\\HuffmanCode\\压缩文.cod",ios::binary);
char c;
int flag=0,tmp=0,n1=0,n2=0;
while(in.get(c))
{
flag++;
n1++;
tmp=tmp*2+c-'0';
if(flag==8)
{
n2++;
flag=0;
out<<(unsigned char)(tmp);
tmp=0;
}
}
if(flag%8!=0) out<<(unsigned char)(tmp),n2++;
out<<(unsigned char)(flag%8);
n2++;
cout<<" ***压缩成功*** "<<endl;
in.close();
out.close();
cout<<"压缩比为 :";
cout<<(100.0*n2)/n1<<"%"<<endl;
DWORD endTime=GetTickCount();
outf<<"压缩哈夫曼编码文运行时间为::"<<endTime-startTime<<"ms"<<endl;
}
void Unzip()
{
DWORD startTime=GetTickCount();
ofstream outf("D:\\C,C++\\数据结构\\HuffmanCode\\计时.txt",ios::app);
ifstream inf("D:\\C,C++\\数据结构\\HuffmanCode\\压缩文.cod",ios::binary);
inf.seekg(0,ios::end);
int n=inf.tellg();
inf.close();
ifstream in("D:\\C,C++\\数据结构\\HuffmanCode\\压缩文.cod",ios::binary);
ofstream out("D:\\C,C++\\数据结构\\HuffmanCode\\解压编码文.txt");
char c;
while(in.get(c))
{
unsigned char ch=c;
int ans=(int)ch;
if(n==2)
{
in.get(c);
ch=c;
int t=(int)ch;
int res=pow(2,t-1);
for(int i=t-1;i>=0;i--)
{
int tmp=ans/res;
ans%=res;
res/=2;
out<<tmp;
}
break;
}
int res=pow(2,7);
for(int i=7;i>=0;i--)
{
int tmp=ans/res;
ans%=res;
res/=2;
out<<tmp;
}
n--;
}
cout<<" ***解压成功*** "<<endl;
in.close();
out.close();
DWORD endTime=GetTickCount();
outf<<"解压压缩文运行时间为::"<<endTime-startTime<<"ms"<<endl;
}
void Transfer(HuffmanTree hf,int n)
{
DWORD startTime=GetTickCount();
ofstream outf("D:\\C,C++\\数据结构\\HuffmanCode\\计时.txt",ios::app);
ifstream in("D:\\C,C++\\数据结构\\HuffmanCode\\解压编码文.txt");
ofstream out("D:\\C,C++\\数据结构\\HuffmanCode\\解压哈夫曼解码文.txt");
cout<<" ***解压码文如下*** "<<endl;
int now=2*n-1;
char c;
while(in.get(c))
{
if(c=='1') now=hf.Hfm[now].rchild;
else now=hf.Hfm[now].lchild;
if(hf.Hfm[now].rchild==0 && hf.Hfm[now].lchild==0)
{
out<<decmp[now];
now=2*n-1;
}
}
in.close();
out.close();
DWORD endTime=GetTickCount();
outf<<"将解压缩后的哈夫曼编码解码运行时间为::"<<endTime-startTime<<"ms"<<endl;
}
int main()
{
HuffmanTree hf;
int n;
while(true)
{
system("pause");
system("cls");
Menu_Show();
int m1;
cout<<"请输入你要进行的操作 :";
cin>>m1;
switch(m1)
{
case 1:Option_1(n); break;
case 2:Option_2(hf,n);break;
case 3:Option_3(hf,n);break;
case 4:Option_4(hf,n);break;
case 5:Option_5(); break;
case 6:Unzip(); break;
case 7:Transfer(hf,n);break;
default:return 0; break;
}
}
return 0;
}