哈夫曼树编码译码Word格式文档下载.docx
- 文档编号:16990592
- 上传时间:2022-11-27
- 格式:DOCX
- 页数:21
- 大小:21.58KB
哈夫曼树编码译码Word格式文档下载.docx
《哈夫曼树编码译码Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《哈夫曼树编码译码Word格式文档下载.docx(21页珍藏版)》请在冰豆网上搜索。
#defineMAXSIZE60
/************************************定义赫夫曼树结构体*******************************************/
/************************************************定义堆结构体**********************************************************/
floatkey;
//关键字项
intotherinfo;
//其他数据项(此题目中用不到)
}RedType;
RedTyper[MAXSIZE+1];
//r[0]闲置用作哨兵
intlength;
//顺序表长度
}SqList;
/**************************************************全局变量*************************************************************/
HuffmanTreeHT;
//赫夫曼树
HuffmanCodeHC;
//码值
FILE*fp,*fp1,*fp2;
inta[30]={0};
floatb[30];
float*w;
//权
/****************************************测试解码(可以输入一个不正确的二进制码串)**************************************/
voidtestdecode()
{
charstr[200];
//存放自己输入的码子
intp,p1,i;
//解码的线索
charch;
printf("
\n请根据以上各个字符的编码输入一串二进制码字(200个以内):
\n"
);
gets(str);
以上码子解码后为:
p=59;
//最初令p为树根整数,p由根顺着树枝一直到树叶
i=0;
ch=str[i++];
while(ch!
='
\0'
)
{
for(;
ch!
&
&
(HT[p].lchild!
=0||HT[p].rchild!
=0);
)
{
if(ch=='
0'
{
p=HT[p].lchild;
}
elseif(ch=='
1'
p=HT[p].rchild;
else
{
printf("
\n你输入了'
'
之外的字符,无法正确译码,请检查!
return;
//直接结束
ch=str[i++];
//下一个码字不断的取下一个
}
if(p<
=30)//小于等于30的时候才正确,有可能最后一位p还没有在1-30范围内的时候就没有二进制码了,也就是说二进制码最后不完整。
switch(p)
{
case27:
"
break;
case28:
."
break;
case29:
"
case30:
default:
%c"
p+96);
}
p1=p;
//让p1记住p
//这里p要重置为59,因为经过上面的程序p已经变化了,不重置为1则HT[p].lchild!
=0所以for语句无法进行!
!
}//while循环
if(p1>
30)
printf("
\n以上正确译出了前面的字符,由于你输入的二进制码不完整,最后一位字符无法译出,请检查!
}
/*******************************************下面是解码*********************************************************/
voiddecode()
intp;
\n\n对码子解码后的如下:
fp1=fopen("
bianma.txt"
r"
if(!
fp1)
cannotopenthisfile!
exit(0);
//最初令p为任意一个非零整数,p由根顺着树枝一直到树叶
ch=fgetc(fp1);
fp2=fopen("
jiema.txt"
w"
if(!
fp2)
=EOF)
HT[p].lchild!
=0;
else
ch=fgetc(fp1);
fprintf(fp2,"
break;
fprintf(fp2,"
fprintf(fp2,"
fclose(fp1);
fclose(fp2);
/*******************************************求最小权值*********************************************************/
voidminweight()
floatWeight=0;
inti;
for(i=0;
i<
30;
i++)
Weight=Weight+strlen(HC[i+1])*b[i];
最小权值是:
%f\n"
Weight);
/*******************************************打印码子**********************************************************/
voidprintcode()
fp=fopen("
Huffman.txt"
fp)
\n原英文文章经编码后如下:
ch=fgetc(fp);
if(ch>
96&
ch<
123)//小写字母
%s"
HC[ch-96]);
fputs(HC[ch-96],fp1);
//输出到文件里面
ch=fgetc(fp);
continue;
}
if(ch>
64&
91)//大小字母
HC[ch-64]);
fputs(HC[ch-64],fp1);
if(ch=='
HC[27]);
fputs(HC[27],fp1);
ch=fgetc(fp);
continue;
.'
HC[28]);
fputs(HC[28],fp1);
'
HC[29]);
fputs(HC[29],fp1);
\n'
HC[30]);
fputs(HC[30],fp1);
\n\n"
fclose(fp);
/*****************************************堆排序****************************************************/
voidHeapAdjust(SqList&
L,ints,intm)
RedTyperc;
intj;
rc=L.r[s];
for(j=2*s;
j<
=m;
j*=2)
if(j<
m&
L.r[j].key>
L.r[j+1].key)//即使等于也不要动,不用加1
++j;
if(rc.key<
=L.r[j].key)//即使等于也不要动,直接跳出来
L.r[s]=L.r[j];
s=j;
L.r[s]=rc;
voidselect(HuffmanTreet,inti,int&
s1,int&
s2)
{//此函数被调用一次则就用堆排序选择两个最小的赋给s1和s2
SqListL;
intj,k,n=1;
L.length=0;
for(j=1;
=i;
j++)
if(t[j].parent!
=0)
continue;
L.r[n].key=t[j].weight;
//赋值好,用堆排序
L.r[n].otherinfo=j;
//存放序号,j是一直在加一的,循环一次加1,但是n不是的只有在符合条件的情况下才加1
n++;
L.length++;
//这样写很巧妙的
for(k=L.length/2;
k>
0;
--k)
HeapAdjust(L,k,L.length);
s1=L.r[1].otherinfo;
//最小的选出来了!
/***把最小的换到最下面***/
rc=L.r[1];
L.r[1]=L.r[L.length];
//此次的select函数,进行堆排序的只有L.length个(parent!
=0的没有在里面),所以这里是L.length而不是i
L.r[L.length]=rc;
HeapAdjust(L,1,L.length-1);
s2=L.r[1].otherinfo;
//次小的选出来了(这里当输入1428四个数时,第一次选出的s1=1,s2=3是对的,但第二次选出的s1=5,但s2是随机数)
/**************************************赫夫曼编码***************************************************/
voidHuffmanCoding(HuffmanTree&
HT,HuffmanCode&
HC,float*w,intn)//算法6.12
//w存放n个字符的权值(均>
0),构造赫夫曼树HT,并求出n个字符的赫夫曼编码HC
intm,i,s1,s2,start,k;
unsignedc,f;
HuffmanTreep;
char*cd;
if(n<
=1)
return;
m=2*n-1;
w=(float*)malloc(30*sizeof(float));
*(w+i)=b[i];
HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));
//0号单元未用
for(p=HT+1,i=1;
=n;
++i,++p,++w)
(*p).weight=*w;
(*p).parent=0;
(*p).lchild=0;
(*p).rchild=0;
for(i=n+1;
++i,++p)
(*p).parent=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;
//最小的和次小的双亲已经不为0了,下次就不在它两中间找最小的和次小的了。
HT[i].lchild=s1;
HT[i].rchild=s2;
HT[i].weight=HT[s1].weight+HT[s2].weight;
}//建立赫夫曼树也容易,关键是select这个子函数!
赫夫曼树如下表:
);
__________________________________________________________________\n"
|_number__|__name__|___weight___|__parent__|__lchild__|__rchild__|\n"
for(k=1;
k<
k++)
if(k<
27)
|___%2d____|__%c和%c__|__%f__|____%2d____|____%2d____|____%2d____|\n"
k,k+64,k+96,HT[k].weight,HT[k].parent,HT[k].lchild,HT[k].rchild);
if(k==27)
|___%2d____|___,____|__%f__|____%2d____|____%2d____|____%2d____|\n"
k,HT[k].weight,HT[k].parent,HT[k].lchild,HT[k].rchild);
if(k==28)
|___%2d____|___.____|__%f__|____%2d____|____%2d____|____%2d____|\n"
if(k==29)
|___%2d____|__空格__|__%f__|____%2d____|____%2d____|____%2d____|\n"
if(k==30)
|___%2d____|__换行__|__%f__|____%2d____|____%2d____|____%2d____|\n"
if(k>
30)
|___%2d____|________|__%f__|____%2d____|____%2d____|____%2d____|\n"
HC=(HuffmanCode)malloc((n+1)*sizeof(char*));
cd=(char*)malloc(n*sizeof(char));
cd[n-1]='
;
for(i=1;
i++)
start=n-1;
//这里f=HT[f].parent是很巧妙的!
for(c=i,f=HT[i].parent;
f!
c=f,f=HT[f].parent)//f=HT[i].parentf!
=0是结束条件,所有的编码最后都要回到HT[m],而只有HT[m]的parent是0!
//从叶子到根逆向求编码
if(HT[f].lchild==c)//c是左孩子则码值是0
cd[--start]='
//这样逆着输,当我们正序输出的时候就恰好是想要的编码了!
else
HC[i]=(char*)malloc((n-start)*sizeof(char));
//为第i个字符编码分配空间
strcpy(HC[i],&
cd[start]);
//从cd复制编码(串)到HC,这里的&
cd[start]是一个地址
free(cd);
//释放工作空间
经赫夫曼编码后码值如下:
=26;
%c和%c---->
%f---->
"
i+64,i+96,HT[i].weight);
puts(HC[i]);
---->
%s\n"
HT[27].weight,HC[27]);
.---->
HT[28].weight,HC[28]);
空格---->
HT[29].weight,HC[29]);
换行---->
%s\
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 哈夫曼树 编码 译码