📄 asd.cpp
字号:
#define MAX 100
#include<iostream>
#include<stdio.h>
using namespace std;
typedef struct htnode{
char data; //结点值
unsigned int weight;
unsigned int parent,lchild,rchild;
}htnode;
typedef struct{
char cd[MAX];
int start;
}huffmancode;
htnode ht[2*MAX];
huffmancode hc[MAX],code;
void crthuffmantree()
{FILE *fp;
char filename[15];
unsigned int m,n,i,s1,s2,m1,m2,l,k;
cout<<endl;
cout<<"--------新建哈夫曼树--------"<<endl;
cout<<"请输入哈夫曼树的结点个数:";
cin>>n;
if(n<=1) return;
cout<<"请输入结点内容及权值:"<<endl;
for(i=1;i<=n;i++)
{ cout<<i<<"=>";
cin>>ht[i].data;
cout<<"权值:";
cin>>ht[i].weight;
cout<<endl;
}
m=2*n-1;
for(i=1;i<=n;i++)
ht[i].lchild=ht[i].rchild=ht[i].parent=0;
for(;i<=m;i++)
ht[i].data=ht[i].weight=ht[i].lchild=ht[i].rchild=ht[i].parent=0;
//建哈夫曼树
for(i=n+1;i<=m;i++)
{m1=m2=32767;
for(k=1;k<=i-1;k++){
if(ht[k].parent==0){
if(ht[k].weight<m1){
m1=ht[k].weight;
s1=k;}
}
}
for(l=1;l<=i-1;l++){
if(ht[l].parent==0){
if((ht[l].weight<m2)&&(l!=s1)){
m2=ht[l].weight;
s2=l;}
}
}
ht[s1].parent=i; ht[s2].parent=i;
ht[i].lchild=s1; ht[i].rchild=s2;
ht[i].weight=ht[s1].weight+ht[s2].weight;
}
/*for(i=n+1;i<=m;i++) 建哈夫曼树的另一种算法
{m1=m2=32767;
l=r=0;
for(k=1;k<=i-1;k++)
if(ht[k].parent==0)
if(ht[k].weight<m1)
{m2=m1;
r=l;
m1=ht[k].weight;
l=k;
}
else if(ht[k].weight<m2)
{m2=ht[k].weight;
r=k;
}
ht[l].parent=i; ht[r].parent=i;
ht[i].lchild=l; ht[i].rchild=r;
ht[i].weight=ht[l].weight+ht[r].weight;
}*/
cout<<"哈夫曼树建立成功"<<endl;
cout<<"请输入存储哈夫曼树文件的文件名:"; //将哈夫曼树存储在文件hfmtree中
cin>>filename;
if((fp=fopen(filename,"wb"))==NULL){
cout<<"不能打开该文件"<<endl;
exit(0);}
for(i=1;i<=m;i++)
if(fwrite(&ht[i],sizeof(struct htnode),1,fp)!=1)
cout<<"文件写入错误"<<endl;
fclose(fp);
cout<<"--------操作完毕--------"<<endl<<endl;
}
//----------------------哈夫曼编码--------------------------
void haffumancoding()
{FILE *fp,*fop;
char ch,filename[15],file[15];
unsigned int m,n,i,c,f,k,t;
cout<<endl;
cout<<"--------哈夫曼编码--------"<<endl;
cout<<"请确认哈夫曼树的结点数:";
cin>>n;
m=2*n-1;
cout<<"将哈夫曼树调入内存,请输入存储哈夫曼树文件的文件名:";
cin>>filename;
if((fp=fopen(filename,"rb"))==NULL){
cout<<"不能打开该文件"<<endl;
exit(0);}
for(i=1;i<=m;i++)
fread(&ht[i],sizeof(struct htnode),1,fp);
fclose(fp);
for(i=1;i<=n;i++){ //哈夫曼编码
code.start=n+1;
c=i;
f=ht[i].parent;
while(f!=0)
{if(ht[f].lchild==c)
code.cd[--code.start]='0';
else code.cd[--code.start]='1';
c=f;
f=ht[f].parent;
}
hc[i]=code;
}
/* cout<<"哈夫曼编码输出为:"<<endl; //结点值及其编码输出
cout<<"结点=>编码"<<endl;
for(i=1;i<=n;i++){
cout<<ht[i].data<<"=>";
for(k=hc[i].start;k<=n;k++)
cout<<hc[i].cd[k];
cout<<endl;}
cout<<endl;*/
cout<<"请输入待编码文本文件的文件名:";
cin>>filename;
if((fp=fopen(filename,"r"))==NULL){
cout<<"不能打开该文件"<<endl;
exit(0);}
ch=fgetc(fp);
cout<<"请输入存储哈夫曼编码文件的文件名:";
cin>>file;
if((fop=fopen(file,"w+"))==NULL){
cout<<"不能打开该文件"<<endl;
exit(0);}
while(ch!='#')
{for(i=1;i<=n;i++){
if(ht[i].data==ch){
t=i;
break;}
}
for(k=hc[t].start;k<=n;k++){
fputc(hc[t].cd[k],fop);} //写入编码文件
ch=fgetc(fp);
}
fclose(fp);
fclose(fop); //勿忘关闭文件,否则可能导致数据丢失
cout<<"--------操作完毕--------"<<endl<<endl;
}
//---------------------编码输出---------------------------------
void codeoutput()
{FILE *fp;
char ch,filename[10];
cout<<endl;
cout<<"--------哈夫曼编码代码输出--------"<<endl; //打开文件codefile,完整输出编码字符串
cout<<"请输入存储编码文件的文件名:";
cin>>filename;
if((fp=fopen(filename,"r"))==NULL){
cout<<"不能打开该文件"<<endl;
exit(0);}
cout<<"代码输出=》";
ch=fgetc(fp);
while(ch!=EOF)
{putchar(ch);
ch=fgetc(fp);
}
fclose(fp);
cout<<endl;
cout<<"--------操作完毕--------"<<endl<<endl;
}
//-------------------哈夫曼树输出-------------------------------
void treeoutput()
{FILE *fp;
char filename[15];
unsigned int m,n,i;
cout<<endl;
cout<<"--------哈夫曼树输出--------"<<endl;
cout<<"请确认哈夫曼树的结点数:";
cin>>n;
m=2*n-1;
cout<<"请输入存储哈夫曼树文件的文件名:";
cin>>filename;
if((fp=fopen(filename,"rb"))==NULL){
cout<<"不能打开该文件"<<endl;
exit(0);}
for(i=1;i<=m;i++){
fread(&ht[i],sizeof(struct htnode),1,fp);
cout<<ht[i].data<<" "<<ht[i].weight<<" "<<ht[i].parent<<" "
<<ht[i].lchild<<" "<<ht[i].rchild<<endl;
}
fclose(fp);
cout<<"--------操作完毕--------"<<endl<<endl;
}
//---------------哈夫曼译码----------------------------------
void decoding()
{FILE *fp;
char ch,filename[15],dc[2*MAX];
unsigned int m,n,i,c,f,r,t,k,start[MAX],d[MAX],s,a,b=0;
cout<<endl;
cout<<"--------哈夫曼译码--------"<<endl;
cout<<"请确认哈夫曼树的结点数:";
cin>>n;
m=2*n-1;
cout<<"将哈夫曼树调入内存,请输入存储哈夫曼树文件的文件名:";
cin>>filename;
if((fp=fopen(filename,"rb"))==NULL){
cout<<"不能打开该文件"<<endl;
exit(0);}
for(i=1;i<=m;i++)
fread(&ht[i],sizeof(struct htnode),1,fp); //将哈夫曼树读入内存
fclose(fp);
for(i=1;i<=n;i++){ //哈夫曼编码
code.start=n+1;
c=i;
f=ht[i].parent;
while(f!=0)
{if(ht[f].lchild==c)
code.cd[--code.start]='0';
else code.cd[--code.start]='1';
c=f;
f=ht[f].parent;
}
hc[i]=code;
}
i=1;
cout<<"请输入存储编码信息的文件:";
cin>>filename;
if((fp=fopen(filename,"r"))==NULL){
cout<<"不能打开该文件"<<endl;
exit(0);}
ch=fgetc(fp);
while(ch!=EOF)
{dc[i]=ch;
i++;
ch=fgetc(fp);
}
fclose(fp);
for(i=1;i<=n;i++)
start[i]=hc[i].start; //将每个字符的起始存储位置依次存入数组start[MAX]
cout<<"请输入译码后文件存储的文件名:";
cin>>filename;
if((fp=fopen(filename,"w+"))==NULL){
cout<<"不能打开该文件"<<endl;
exit(0);}
t=1;
s=1;
for(i=1;i<=n;i++) //*译码过程*
{for(r=t,k=hc[i].start;k<=n&&hc[i].cd[k]==dc[r]&&dc[r]!=NULL;r++,k++){
if(r-t==n-start[i]){ //找到对应编码的结点值
d[s]=r-t+1;
fputc(ht[i].data,fp);
for(a=1;a<=s;a++) b+=d[a];
t=b+1;
b=0;
s++;
i=0;
break;}
}
}
fclose(fp);
cout<<"------操作完毕------"<<endl<<endl;
}
void main()
{char w;
cout<<" *********************"<<endl;
cout<<" *哈夫曼编/译码器系统*"<<endl;
cout<<" *********************"<<endl;
cout<<" ======计0306 曾庚卓 20032969 "<<endl<<endl;
cout<<" *********************************************************"<<endl;
cout<<" I===>>新建哈夫曼树 E===>>哈夫曼编码 D===>>哈夫曼译码"<<endl;
cout<<" O===>>编码输出 T===>>哈夫曼树输出 Q===>>退出 "<<endl;
cout<<" *********************************************************"<<endl<<endl;
do
{
cout<<"请按键选择:";
cin>>w;
switch(w)
{
case 'I':crthuffmantree();break;
case 'E':haffumancoding();break;
case 'D':decoding();break;
case 'O':codeoutput();break;
case 'T':treeoutput();break;
}}
while(w!='Q');
cout<<" -----------结束任务!-------------"<<endl;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -