哈弗曼编译码器 罗忠霖Word格式.docx
《哈弗曼编译码器 罗忠霖Word格式.docx》由会员分享,可在线阅读,更多相关《哈弗曼编译码器 罗忠霖Word格式.docx(15页珍藏版)》请在冰豆网上搜索。
stdio.h>
stdlib.h>
string.h>
conio.h>
typedefstruct
{
charchr1;
intweight;
intparent,lchild,rchild;
}HTNode,*HuffmanTree;
charchr;
intw1;
char*code;
//编码
}Ch;
//字符和对应的权值及编码
voidSelect(HuffmanTree&
HT1,intj,int&
s1,int&
s2);
voidHuffmanCoding(HuffmanTree&
HT,Ch*w,intn);
//构造哈夫曼树HT
voidencoding(HuffmanTree&
HT,Ch*ch,intn);
//求每个字符的哈夫曼编码
voidEncoding(Ch*ch1,intn);
voidDecoding(HuffmanTree&
HT,intsum);
//译码
voidcaidan();
voidPrintf();
voidmain()
FILE*p;
intchoice,n1,w2=1;
inti,flag=1,m;
charch;
HuffmanTreeHTr;
Ch*c;
caidan();
while(flag)
{
loop:
printf("
\n*请选择(0-5):
"
);
scanf("
%d"
&
choice);
switch(choice)
{
case1:
printf("
请输入字符集大小n="
scanf("
n1);
c=(Ch*)malloc((n1+1)*sizeof(Ch));
flushall();
for(i=1;
i<
=n1;
i++)
{
printf("
请输入字符及其权值:
scanf("
%c%d"
ch,&
w2);
c[i].chr=ch;
c[i].w1=w2;
flushall();
}
HuffmanCoding(HTr,c,n1);
encoding(HTr,c,n1);
break;
case2:
Encoding(c,n1);
case3:
Decoding(HTr,n1);
case4:
Printf();
case5:
m=2*n1-1;
if((p=fopen("
TreePrint.txt"
"
w"
))==NULL)
Filecouldnotbeopened\n"
else
{
fprintf(p,"
\n哈夫曼树的构造如下所示:
\n"
结点weightparentlchildrchild"
for(i=1;
i<
=m;
i++)
{
fprintf(p,"
\n%4d%8d%8d%8d%8d"
i,HTr[i].weight,
HTr[i].parent,HTr[i].lchild,HTr[i].rchild);
}
}
fclose(p);
printf("
for(i=1;
{
HTr[i].parent,HTr[i].lchild,HTr[i].rchild);
break;
case0:
flag=0;
你选择了推出程序,欢迎使用!
break;
default:
gotoloop;
}
}
}
voidcaidan()
{printf("
\n*****************哈夫曼编译器*****************\n"
printf("
1.初始化\n"
2.编码\n"
3.译码\n"
4.打印代码文件\n"
5.打印哈夫曼树\n"
6.退出系统\n"
**********************************************\n"
s2)
//在HT[1...j]中选择parent为0且weight最小的两个结点,其序号分别为s1和s2
inti=0,d=0,h;
for(i=j;
i>
=0;
i--)
{
if(HT1[i].parent!
=0)//在双亲不为0的条件下
continue;
if(d==0)//用s1记录第一个双亲为0的元素所在的位置
s1=i;
d++;
}
elseif(d==1)//用s2记录第而个双亲为0的元素所在的位置
{
s2=i;
elseif(d==2)
{
if(HT1[s1].weight<
=HT1[s2].weight)//s2用于存储最小值的位置
{
h=s1;
s1=s2;
s2=h;
}
if(HT1[i].weight<
HT1[s1].weight)//s1用于存放次小值的位置
s1=i;
}
HT,Ch*w,intn)
//*w存放n个字符的权值(均>
0),构造哈夫曼树HT
FILE*p;
inti,j,m,s1,s2;
if(n<
=1)return;
m=2*n-1;
//树的结点总数
HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));
//0号单元未用
for(i=1;
=n;
i++)
{//初始化
HT[i].chr1=w[i].chr;
HT[i].weight=w[i].w1;
//
HT[i].parent=0;
HT[i].lchild=0;
HT[i].rchild=0;
for(i=n+1;
HT[i].weight=0;
i++)//建哈夫曼树
//在HT[1...i-1]中选择parent为0且weight最小的两个结点,其序号分别为s1和s2。
Select(HT,i-1,s1,s2);
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;
if((p=fopen("
hfmTree.txt"
else
fprintf(p,"
fprintf(p,"
i,HT[i].weight,
HT[i].parent,HT[i].lchild,HT[i].rchild);
fclose(p);
HT,Ch*ch,intn)
{//---从叶子到根逆向求每个字符的哈夫曼编码---
inti,c,f,start;
char*cd;
cd=(char*)malloc(n*sizeof(char));
//分配求编码的工作空
cd[n-1]='
\0'
;
//编码结束符。
++i)//逐个字符求哈夫曼编码
start=n-1;
//编码结束符位置
for(c=i,f=HT[i].parent;
f!
c=f,f=HT[f].parent)//从叶子到根逆向求编码
if(HT[f].lchild==c)cd[--start]='
0'
elsecd[--start]='
1'
ch[i].code=(char*)malloc((n-start)*sizeof(char));
//为第i个字符编码分配空间
strcpy(ch[i].code,&
cd[start]);
//从cd复制编码(串)到code
free(cd);
//释放工作空间
}
voidEncoding(Ch*ch1,intn)
//利用已经建立的哈弗曼树编码对输入的字符进行哈弗曼编码
FILE*q1,*q2;
//chara[100];
//用于存放输入的字符
charnum[1000],c;
char*p=num;
//用于存放字符对应的哈弗曼编码
inti,j;
if((q1=fopen("
ToBeTran.txt"
r"
rewind(q1);
while(!
feof(q1))//依次判断字符的对应的哈弗曼编码
c=fgetc(q1);
for(j=1;
j<
j++)
if(c==ch1[j].chr)
printf("
%c:
%s"
ch1[j].chr,ch1[j].code);
strcpy(p,ch1[j].code);
p=p+strlen(ch1[j].code);
}//如果找到就把对应的哈弗曼编码复制到字符数组num中
*p='
\n得到的编码是:
for(i=0;
num[i]!
='
i++)//输出字符对应的哈弗曼编码
if(i==50)printf("
//当输出50个字符时,进行换行
%c"
num[i]);
fclose(q1);
if((q2=fopen("
CodeFile.txt"
i=0;
while(num[i]!
)
if(i==50)fprintf(q2,"
fprintf(q2,"
num[i++]);
fclose(q2);
HT,intsum)//译码
{
//charcode1[1000];
//用于存放输入的密码
chara1[100],c;
//用于存放翻译好的字符
intn=0,i=0,b=2*sum-1;
r+"
feof(p))
c=fgetc(p);
if(c=='
)b=HT[b].lchild;
//当遇到0时指向哈弗曼树的左子树
)b=HT[b].rchild;
//当遇到1时指向哈弗曼树的右子树
if(HT[b].lchild==0&
&
HT[b].rchild==0)//当左右子树均为空时表明已找到对应的字符
a1[n++]=HT[b].chr1;
b=2*sum-1;
//将对应的字符放在数组a1中,并重新设置b的值继续翻译
a1[n]='
i=0;
while(a1[i]!
)//输出翻译好的字符
a1[i++]);
TextFile.txt"
得到的翻译结果是:
while(a1[i]!
if(i==50)fprintf(p,"
voidPrintf()
FILE*p;
得到的编码是:
feof(p))
inti=0;
if(i==50)printf("
printf("
fgetc(p));
i++;
4.结果显示:
四、实验小结及体会:
通过本实验能够更好掌握文件指针的操作运用,加深理解,运用它解决一些实际问题,且能教熟练掌握数的结构以及哈弗曼算法。