哈夫曼编解码完整c程序代码.docx
《哈夫曼编解码完整c程序代码.docx》由会员分享,可在线阅读,更多相关《哈夫曼编解码完整c程序代码.docx(15页珍藏版)》请在冰豆网上搜索。
哈夫曼编解码完整c程序代码
1)内容:
利用Huffman编码进行通信可以大大提高信道的利用率,缩短信息传输时间,降低传输成本。
但是,这要求在发送端通过一个编码系统对待传数据进行预先编码,在接收端进行解码。
对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编/解码系统。
2)要求:
一个完整的huffman编解码系统应该具有以下功能:
初始化(Initialization)。
从终端读入字符集大小n,以及n个字符和n个权值,建立Huffman树,并将它存入hfmTree中。
编码(Encoding)。
利用已经建好的Huffman树(如果不在内存,则应从文件hfmTree中读取),对文件ToBeTran中的正文进行编码,然后将结果存入文件hfmTree中读取),对文件ToBeTran中的正文进行编码,然后将结果存入文件CodeFile中。
解码(Decoding)。
利用已经建立好的Huffman树将文件CodeFile中的代码进行解码,结果存入TextFile中。
打印代码文件(Print)。
将文件CodeFile以紧凑的格式显示在终端上,每行50个代码。
同时将此字符形式的编码文件写入文件CodePrint中。
打印Huffman树(TreePrinting)。
将已经在内存中的Huffman树以直观的形式(树或者凹入的形式)显示在终端上,同时将此字符形式的Huffman树写入文件TreePrint中。
3)测试数据:
用下表给出的字符集和频度的实际统计数据建立Huffman树,并对以下报文进行编码和译码:
“THISPROGRAMISMYFAVORITE”。
字符
A
B
C
D
E
F
G
H
I
J
K
L
M
频度
186
64
13
22
32
103
21
15
47
57
1
5
32
20
字符
N
O
P
Q
R
S
T
U
V
W
X
Y
Z
频度
57
63
15
1
48
51
80
23
8
18
1
16
1
完整代码如下:
#include
#include
#include
#defineN100
int*w;
char*c,stack[N],code[N][N];
ints1,s2;
typedefstructHuffmanTree
{
intweight;
intparent;
intlchild;
intrchild;
}HuffmanTree,*Huff;
voidmenu(void);
voidSelect(structHuffmanTreeHT[],inti);
voidHuffmanTree(Huff&HT,int*w,intn);
voidvisite(HuffHT,inti,intflag,intrear);
voidtranslatef(char*scource,char*save,intn);
booluncodef(FILE*fp1,FILE*fp2,HuffHT,intn);
intinputHuff();
voidscreanio(intn);
voidfileio(intn);
intinitHuff();
voidPrint_tree(intn,HuffHT);
voidConvert_tree(HuffHT,unsignedcharT[100][100],inttt[100][100],ints,int*i,intj);
voiddecoding(intn);
voidcoding(intn);
voidmain()
{
intn=0;
menu();
HuffHT;
charstate;
do
{
std:
:
cout<<"input:
\n";
std:
:
cin>>state;fflush(stdin);//读取状态
switch(state)
{
case'I':
n=inputHuff();HuffmanTree(HT,w,n);std:
:
cout<<"\nHuffmanTree初始化完毕\n";break;
case'C':
coding(n);break;
case'D':
decoding(n);break;
case'P':
Print_tree(n,HT);break;
case'Q':
break;
}
}while(state!
='Q');
}
voidmenu()//显示菜单函数
{
std:
:
cout<<"===========HuffmanCoding===========\n";
std:
:
cout<<"input\t\tdo\n";
std:
:
cout<<"I\t\tInit_HUffTree\n";//初始化huffmantree
std:
:
cout<<"C\t\tCoding\n";//对ToBeTran.txt文件中的字符进行编码到CodeFile.txt中
std:
:
cout<<"D\t\tUnCoding\n";//对CodeFile.txt中的01序列进行解码到TextFile.txt
std:
:
cout<<"P\t\tPrintTree\n";//打印哈夫曼树
std:
:
cout<<"Q\t\tquit\n";
std:
:
cout<<"请初始化哈夫曼树再执行后面的操作\n";
}
intinputHuff()//输入各个字母及其权值
{
inti=1,n=0;
intww[28];
charcc[28];
while
(1)
{
std:
:
cout<<"inputtheletter(input'#'tostop):
";
cc[i]=std:
:
cin.get();fflush(stdin);
if(cc[i]=='#')
break;
std:
:
cout<<"inputtheweight:
";
std:
:
cin>>ww[i];fflush(stdin);
n++;
i++;
}
w=(int*)malloc(sizeof(int)*(n+1));
c=(char*)malloc(sizeof(char)*(n+1));
for(i=0;i{
w[i]=ww[i];
c[i]=cc[i];
}
returnn;
}
voidHuffmanTree(Huff&HT,int*w,intn)//初始化哈夫曼树
{
intm,i;
m=n*2-1;
HT=(structHuffmanTree*)malloc(sizeof(structHuffmanTree)*(m+1));
HT[0].lchild=0;
HT[0].parent=0;
HT[0].rchild=0;
HT[0].weight=0;
for(i=1;i{
HT[i].weight=i<=n?
w[i]:
0;
HT[i].lchild=HT[i].rchild=HT[i].parent=0;
}
for(i=n+1;i<=m;i++)
{
Select(HT,i);
HT[i].lchild=s1;
HT[i].rchild=s2;
HT[i].weight=HT[s1].weight+HT[s2].weight;
HT[s1].parent=HT[s2].parent=i;
}
}
voidSelect(structHuffmanTreeHT[],inti)//在HT[1..i-1]中选择parent为0且weight为最小的两个结点
{
intj;
for(j=1;j
{
if(HT[j].parent==0)
{
s1=j;s2=j;gotoflag;
}
}
flag:
for(j=s1+1;j
{
if(HT[j].parent==0)
{
if(HT[s1].weight>=HT[j].weight)
{
s2=s1;
s1=j;
}
if(HT[s2].weight>HT[j].weight&&j!
=s1)
s2=j;
if(s1==s2)s2=j;
}
}
}
voidPrint_tree(intn,HuffHT)//以凹入法的形式打印树
{
unsignedcharT[100][100];
inttt[100][100];
inti,j,m=0;
FILE*fp;
Convert_tree(HT,T,tt,0,&m,2*n-1);//将内存中的赫夫曼树转换成凹凸表形式的树,存于数组T中
if((fp=fopen("treeprint.txt","wb+"))==NULL)
printf("Openfiletreeprint.txterror!
\n");
printf("\n以凹凸表形式打印已建好的赫夫曼树:
\n");
for(i=1;i<=2*n-1;i++)
{
for(j=0;T[i][j]!
=0;j++)
{
if(T[i][j]==''){printf("");fputc(T[i][j],fp);}
else
{printf("%d",tt[i][j]);fprintf(fp,"%d\n\n\n",tt[i][j]);}
}
printf("\n");
}
fclose(fp);
printf("\n此字符形式的哈夫曼树已写入文件treeprint.txt中.\n\n");
printf("\n文件treeprint.txt的打开方式要为写字板,若打开方式为记事本,则无法显示凹凸表的形式\n");
}
voidConvert_tree(HuffHT,unsignedcharT[100][100],inttt[100][100],ints,int*i,intj)//将内存中的赫夫曼树转换成凹凸表形式的树,存于数组T中
{
intk,l;
l=++(*i);
for(k=0;k
T[l][k]='';
T[l][k]='#';
tt[l][k]=HT[j].weight;
if(HT[j].lchild)
Convert_tree(HT,T,tt,s+1,i,HT[j].lchild);
if(HT[j].rchild)
Convert_tree(HT,T,tt,s+1,i,HT[j].rchild);
T[l][++k]='\0';
}
voidcoding(intn)//对文件ToBeTran.txt编码到CodeFile.txt
{
FILE*fp1;
HuffHT;
HuffmanTree(HT,w,n);
visite(HT,2*n-1,2,0);
fflush(stdin);
translatef("ToBeTran.txt","CodeFile.txt",n);
fp1=fopen("CodeFile.txt","r");
printf("\n编码已写入文件treeprint.txt中.\n");
fclose(fp1);
}
voiddecoding(intn)//对CodeFile.txt中的01序列进行解码到TextFile.txt
{
FILE*fp1,*fp2;
HuffHT;
HuffmanTree(HT,w,n);
fp1=fopen("CodeFile.txt","r");
fp2=fopen("TextFile.txt","w");
while(uncodef(fp1,fp2,HT,2*n-1));
printf("\n");
printf("\n解码已写入文件TextFile.txt中.\n");
fclose(fp1);
fclose(fp2);
}
voidvisite(HuffHT,inti,intflag,intrear)//通过递归调用visite()函数,得到各个字母的编码,存储于全局变量code[][]中
{
intj=0,k=0;
if(flag==0)
{
stack[rear]='0';
rear++;
}
elseif(flag==1)
{
stack[rear]='1';
rear++;
}
if(HT[i].lchild==0)
{
for(j=0;j{
code[i][j]=stack[j];
}
code[i][j]='#';
rear--;
return;
}
visite(HT,HT[i].lchild,0,rear);
visite(HT,HT[i].rchild,1,rear);
k=rear;
for(j=0;j{
code[i][j]=stack[j];
}
code[i][j]='#';
rear--;
return;
}
voidtranslatef(char*scource,char*save,intn)//读取文件中的字母序列,并根据code[][]将其转换成01序列输出
{
FILE*fp1,*fp2;
charp='';
inti=0,j=0,k=0;
fp1=fopen(scource,"r");
fp2=fopen(save,"w");
p=fgetc(fp1);
printf("\n得到的编码为:
\n");
while(p!
=EOF)
{
for(i=0;i<=n;i++)
{
if(c[i]==p)
{
for(j=0;j='#';j++)
{
fputc(code[i][j],fp2);putchar(code[i][j]);k++;
if(k>=50)
{
k=0;
putchar('\n');
}
}
}
}
p=fgetc(fp1);
}
fclose(fp1);
fclose(fp2);
}
booluncodef(FILE*fp1,FILE*fp2,HuffHT,intn)//通过对树的访问,把文件中01序列转换成一个字母输出。
本函数需循环调用,当读到'\n'时返回false
{
charp='';
if(!
fp1||!
fp2)
{
printf("error");
exit(0);
}
if(HT[n].lchild==0)
{
fputc(c[n],fp2);
returntrue;
}
else
{
p=fgetc(fp1);
if(p==EOF)
{
returnfalse;
}
}
if(p=='0')
{
uncodef(fp1,fp2,HT,HT[n].lchild);
}
elseif(p=='1')
{
uncodef(fp1,fp2,HT,HT[n].rchild);
}
returntrue;
}
/*以下在初始化哈夫曼树时复制粘贴可用,注意第一个为空格,weight为186,复制粘贴时要包括它.输入以#号结束
186
A
64
B
13
C
22
D
32
E
103
F
21
G
15
H
47
I
57
J
1
K
5
L
32
M
20
N
57
O
63
P
15
Q
1
R
48
S
51
T
80
U
23
V
8
W
18
X
1
Y
16
Z
1
#
*/