哈夫曼编码课设说明书Word文件下载.docx
- 文档编号:21138619
- 上传时间:2023-01-27
- 格式:DOCX
- 页数:35
- 大小:166.82KB
哈夫曼编码课设说明书Word文件下载.docx
《哈夫曼编码课设说明书Word文件下载.docx》由会员分享,可在线阅读,更多相关《哈夫曼编码课设说明书Word文件下载.docx(35页珍藏版)》请在冰豆网上搜索。
而树是包含n(n>
0)个结点的有穷集合K,且在K中定义了一个关系N,N满足以下条件:
(1)有且仅有一个结点K0,他对于关系N来说没有前驱,称K0为树的根结点。
简称为根。
(2)除K0外,K中的每个结点,对于关系N来说有且仅有一个前驱。
(3)K中各结点,对关系N来说可以有m个后继(m>
=0)
输入/输出数据:
数据类型:
数据
字符型
权值
浮点型
父结点,左右孩子结点
整型
节点数
开始位置
表A-1主要数据类型
2.算法设计
●构造哈夫曼树的算法
在哈夫曼树中,没有度为1的结点,这类二叉树称为严格二叉树。
那么对于一颗含有n个结点的哈弗曼树共有2n-1个结点所以哈夫曼算法可以用一维数组实现。
显然每个结点的存储结构都应该有一个域存放权值;
构成Huffman树之后,为求编码需从叶子结点出发走一条从叶子到根的路径,而为译码需从根出发走一条从根到叶子的路径。
对每个结点而言,既需知双亲的消息,又需知孩子结点的消息。
因此,可设定一个静态三叉链表来实现。
具体算法描述如下:
structhufmtreenode{//定义哈弗曼树结点数据类型
chardata;
floatweight;
//结点权值
intparent,lchild,rchild;
hufmtree*BuildHuffmanTree(hufmtree*tree){//构建叶子结点已初始化的哈夫曼树
//tree中所有叶子结点已初始化
inti,j,p1,p2,m;
floatsmall1,small2;
m=2*(tree->
n)-1;
for(i=tree->
n;
i<
m;
i++)//初始化所有非叶子结点
{
tree->
node[i].parent=-1;
node[i].lchild=-1;
node[i].rchild=-1;
node[i].weight=0.0;
}
i++)//构建哈夫曼树
small1=small2=MAXVAL;
for(j=0;
j<
=i-1;
j++)
{
if(tree->
node[j].parent==-1&
&
tree->
node[j].weight<
=small1small1=tree->
node[j].weight;
p1=j;
for(j=0;
{
=small2&
(j!
=p1))
small2=tree->
p2=j;
node[p1].parent=tree->
node[p2].parent=i;
node[i].weight=tree->
node[p1].weight+tree->
node[p2].weight;
node[i].lchild=p1;
node[i].rchild=p2;
}
returntree;
}
●哈夫曼编码算法
求哈夫曼编码,实质上就是在已建好的哈夫曼树中,从叶子结点开始,沿结点的双亲域回退到根节点,每回退一步,就走过了哈夫曼树的一个分支,从而得到一位哈夫曼编码值,由于一个字符的哈弗曼编码是从根节点到相应的叶子结点所经过的路径上各分支所组成的0、1序列,因此先得到的分支代码为所求编码的低位码,后得到的分支码为所求编码的高位码。
可以设置一个结构数组用来存放各字符的哈夫曼码信息。
while(!
feof(codefile))
for(i=2*tree->
n-2;
tree->
node[i].lchild>
=0&
node[i].rchild>
ch!
=EOF;
)
{
if(ch=='
0'
i=tree->
node[i].lchild;
elseif(ch=='
1'
node[i].rchild;
else{
printf("
\n存在异常字符%c,不能正确译码。
\n"
ch);
return;
}
if(i==-1)//在哈夫曼树中找不到对应叶子结点
{
printf("
\n编码与当前哈夫曼树结构不相符,不能正确译码。
fclose(decodefile);
return;
ch=fgetc(codefile);
}
3.函数的调用关系图
图A-1各程序模块之间的层次(调用)关系图
4.调试分析
(1)问题1
●问题描述:
编码过程中字符串编码总是缺少很多位,甚至不能编码一些字符。
●问题分析:
字符串编码总是缺少很多位,说明导致这种情况的可能是节点不够多,致使编码没空间存储。
●解决方法:
初始化霍夫曼链表的节点不够,如果假设字符串有n个,那链表节点至少得有2n-1个,比如对4个字符串编码,先在4个字符里选2个权值最小的字符,2个字符权值相加,生成新的一个节点存储,现在还剩3个节点,同理3选2,生成新节点,剩余一个节点最后与上一步生成的节点配对,因此共需要生成3个新节点来存储。
(2)问题2
程序运行中,当创建树时,无法将树的元素存入到其中。
无法存入其中,可能有两方面原因,第一:
没有初始化树,即没有申请空间;
第二方面:
可能是树的结构体定义出现错误。
在树的创建中,首先对其进行初始化,申请存储空间,然后再输入树的元素,经过调试,结果正确。
(3)算法的时间复杂度为O(n²
),空间复杂度为S(n)。
5.测试结果
(1)打开源文件统计各字符及权值信息并存入data.txt文件中
图A-2测试图
(2)将统计出的权值信息进行哈夫曼编码
图A-3测试图
(3)将编码内容存入CodeFile.txt文件中
图A-4测试图
(4)
将CodeFile.txt文件中的内容译码
图A-5测试图
(5)成功译码把原字符信息存入DeCodeFile.txt文件中
图A-6测试图
6.源程序(带注释)
#include<
stdio.h>
conio.h>
stdlib.h>
#defineMAXVAL10000.0
//父结点,左、右孩子结点
};
structhufmtree{//哈弗曼树数据类型
hufmtreenode*node;
//结点数组(根据n的值动态分配)
intn;
//定义叶子结点数
structCodetype{//哈弗曼编码数据类型
char*bits;
//n为为哈夫曼树中叶子结点的数目,编码的长度不可能超过n
intstart;
//编码实际在编码数组里的开始位置
voidSortHufmtree(hufmtree*tree){//将哈夫曼树n个叶子结点由大到小排序
inti,j,k;
hufmtreenodetemp;
if(tree==NULL)
return;
for(i=0;
i++)//利用选择排序对哈弗曼树n个叶子结点由大到小排序
k=i;
for(j=i+1;
node[j].weight>
node[k].weight)
k=j;
if(k!
=i)
temp=tree->
node[i];
tree->
node[i]=tree->
node[k];
node[k]=temp;
Codetype*HuffmanCode(hufmtree*tree){//哈弗曼编码的生成
inti,j,p,k;
Codetype*code;
returnNULL;
code=(Codetype*)malloc(tree->
n*sizeof(Codetype));
i++)
printf("
%c"
tree->
node[i].data);
//打印字符信息
code[i].bits=(char*)malloc(tree->
n*sizeof(char));
code[i].start=tree->
n-1;
j=i;
p=tree->
node[i].parent;
while(p!
=-1){
node[p].lchild==j)
code[i].bits[code[i].start]='
;
else
code[i].start--;
j=p;
p=tree->
node[p].parent;
for(k=code[i].start+1;
k<
k++)//打印字符编码
printf("
%c"
code[i].bits[k]);
);
returncode;
=small1)
{
small1=tree->
p1=j;
small2=tree->
}
hufmtree*CreateHuffmanTreeFromSourceFile(){//通过解析源文件建立哈夫曼树
FILE*textfile,*datafile;
charch,sourcefilename[100];
inti,j=0,n=0;
floatcount[128];
//用于统计字符在源文件中出现的次数,27表示26个英文字母和1个空格字符
hufmtree*tree;
//打开一个源文件
printf("
\n请输入源文件所在路径:
scanf("
%s"
sourcefilename);
if((textfile=fopen(sourcefilename,"
r"
))==NULL){
\n找不到文件%s\n"
for(i=0;
128;
count[i]=0;
//对源文件中各字符的个数统计
ch=fgetc(textfile);
feof(textfile)){
for(i=0;
if(ch==char(i)){
count[i]++;
break;
ch=fgetc(textfile);
//将统计结果写入权值信息文件data.txt中,并构建哈夫曼树
datafile=fopen("
data.txt"
"
w"
if(count[i]!
n++;
fprintf(datafile,"
%d\n"
n);
tree=(hufmtree*)malloc(sizeof(hufmtree));
node=(hufmtreenode*)malloc((2*n-1)*sizeof(hufmtreenode));
n=n;
\n源文件的字符集及其权值信息如下:
fprintf(datafile,"
%c%f\n"
char(i),count[i]);
%c%.0f\n"
node[j].data=char(i);
node[j].weight=count[i];
node[j].parent=-1;
node[j].lchild=-1;
node[j].rchild=-1;
j++;
SortHufmtree(tree);
BuildHuffmanTree(tree);
fclose(textfile);
fclose(datafile);
\n哈夫曼树建立完毕,已将权值信息保存至data.txt\n"
hufmtree*CreateHuffmanTreeByInput(){//通过用户输入建立哈夫曼树
inti,m;
FILE*datafile;
//由用户输入字符与权值信息并将其写入data.txt,同时进行哈夫曼树初始化
请输入字符数:
"
%d"
&
n);
if(n<
\n您的输入有误。
m=2*n-1;
输入第%d个字符及其权值:
i+1);
node[i].data=getche();
scanf("
%f"
node[i].weight);
fprintf(datafile,"
node[i].data,tree->
//哈夫曼树构建
hufmtree*CreateHuffmanTreeFromDataFile(){//通过读取权值信息文件建立哈夫曼树
inti,n;
if((datafile=fopen("
\n哈夫曼树尚未建立\n"
//哈夫曼树初始化
fscanf(datafile,"
fgetc(datafile);
i++){
node[i].data=fgetc(datafile);
fscanf(datafile,"
%f\n"
hufmtree*Encoding(hufmtree*tree){//对源文件进行编码并将其输出至新文件
FILE*textfile,*codefile;
charch,sourcefilename[50];
inti,j;
if(tree==NULL)//如果内存中尚未建立哈夫曼树
{//试从data.txt中读取权值信息并建立哈夫曼树
tree=CreateHuffmanTreeFromDataFile();
if(tree==NULL)
returnNULL;
//读取源文件
//打印源文件内容
\n源文件的原文如下:
}
//编码
\n字符集的哈夫曼编码如下:
code=HuffmanCode(tree);
//将源文件中各字符编码并写入codefile
codefile=fopen("
CodeFile.txt"
fseek(textfile,0,SEEK_SET);
while(!
feof(textfile))
{
if(ch==tree->
node[i].data){
for(j=c
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 哈夫曼 编码 说明书
![提示](https://static.bdocx.com/images/bang_tan.gif)