哈夫曼解码编码实现

本实验基于《程序设计与数据结构》课程,通过构造哈夫曼树对包含26个英文字母的文件进行编码与解码。实验覆盖了哈夫曼树的基本原理,包括路径长度、带权路径长度的概念,以及如何利用概率构造哈夫曼树。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

20172323 2018-2019-1 《程序设计与数据结构》课堂测试报告

课程:《程序设计与数据结构》
班级: 1723
姓名: 李楠
学号: 20172330
实验教师:王志强老师
测试日期:2018年12月10日
必修/选修: 必修

1.测试内容

哈夫曼编码测试
设有字符集:S={a,b,c,d,e,f,g,h,i,j,k,l,m,n.o.p.q,r,s,t,u,v,w,x,y,z}。
给定一个包含26个英文字母的文件,统计每个字符出现的概率,根据计算的概率构造一颗哈夫曼树。
并完成对英文文件的编码和解码。
要求:
(1)准备一个包含26个英文字母的英文文件(可以不包含标点符号等),统计各个字符的概率
(2)构造哈夫曼树
(3)对英文文件进行编码,输出一个编码后的文件
(4)对编码文件进行解码,输出一个解码后的文件
(5)撰写博客记录实验的设计和实现过程,并将源代码传到码云
(6)把实验结果截图上传到云班课

2. 测试过程及结果

基本原理:

哈夫曼树:给定n个权值作为n个叶子结点,构造一棵二叉树,若带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree)。哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近。

路径: 树中一个结点到另一个结点之间的分支构成这两个结点之间的路径。

路径长度:路径上的分枝数目称作路径长度。

树的路径长度:从树根到每一个结点的路径长度之和。

结点的带权路径长度:在一棵树中,如果其结点上附带有一个权值,通常把该结点的路径长度与该结点上的权值之积称为该结点的带权路径长度(weighted path length)

树的带权路径长度:如果树中每个叶子上都带有一个权值,则把树中所有叶子的带权路径长度之和称为树的带权路径长度。

3. 代码链接

(https://gitee.com/CS-IMIS-23/linan20172330newterm)

4. 测试过程中遇到的问题和解决过程

5.参考资料

转载于:https://www.cnblogs.com/linanlalala/p/10111053.html

#include #define MAXBIT 2000 /*定义哈夫曼编码的最大长度*/ #define MAXVALUE 1000 /*定义最大权值*/ #define MAXLEAF 256 /*定义哈夫曼树中最多叶子节点个数*/ #define MAXNODE MAXLEAF*2-1 /*哈夫曼树最多结点数*/ typedef struct { /*哈夫曼编码结信息的构*/ char bit[MAXBIT]; int start; }Hcodetype; typedef struct { /*哈夫曼树结点的结构*/ int weight; int parent; int lchild; int rchild; char ch; }Hnodetype; char ch[MAXVALUE*5]; static int numbers; int number=0; char varyCh[MAXLEAF]; int weight[MAXLEAF]; int pos[256]; int root; char allHc[MAXVALUE*20]; /*----------分析输入的字符串--------------*/ void analyze(char ch[],int numbers,char varyCh[],int weight[],int& number){ int temp[256]={0}; int n=0; for(int i=0;i<numbers;i++){ temp[(int)ch[i]]++; } for(int j=0;j<256;j++){ if(temp[j]!=0){ varyCh[n]=(char)j; weight[n]=temp[j]; pos[j]=n; n++; } } number=n; } void huffmantree(Hnodetype huffnode[MAXNODE]) /*构造哈夫曼树的函数*/ { int i,j,m1,m2,x1,x2; analyze(ch,numbers, varyCh, weight,number); for(i=0;i<number;i++) /*存放哈夫曼树结点的数组huffnode[]初始化*/ { huffnode[i].weight=weight[i]; huffnode[i].parent=-1; huffnode[i].lchild=-1; huffnode[i].rchild=-1; huffnode[i].ch=varyCh[i]; } for(i;i<2*number;i++){ huffnode[i].weight=0; huffnode[i].parent=-1; huffnode[i].lchild=-1; huffnode[i].rchild=-1; } /* for(i=0;i<n;i++) /*输入入N个叶子节点的权值 { printf("please input %d character's weight\n",i); scanf("%d",&huffnode[i].weight); } */ for(i=0;i<number-1;i++){/*开始循环构造哈夫曼树*/ m1=m2=MAXVALUE; //m1拥有最小值 x1=x2=0; //记录一次循环后找到最小和次小节点的位置 for(j=0;j<number+i;j++){ if(huffnode[j].weight<m1&&huffnode[j].parent==-1) { m2=m1;x2=x1;m1=huffnode[j].weight;x1=j; } else if(huffnode[j].weight<m2&&huffnode[j].parent==-1) { m2=huffnode[j].weight;x2=j; } } huffnode[x1].parent=number+i; huffnode[x2].parent=number+i; huffnode[number+i].weight=huffnode[x1].weight+huffnode[x2].weight; huffnode[number+i].lchild=x1; huffnode[number+i].rchild=x2; } } void unhanffman(Hnodetype huffnode[]){ //根据哈夫曼树和所有字符的编码进行译 int i=0; int r=root; //指向根节点 while((allHc[i]!=NULL)){ if(allHc[i]=='0')r=huffnode[r].lchild; else r=huffnode[r].rchild; if(huffnode[r].lchild==-1&&huffnode[r].rchild==-1) { printf("%c",huffnode[r].ch); r=root; } i++; } printf("\n\n"); } void main() { Hnodetype huffnode[MAXNODE]; Hcodetype leafcode[MAXLEAF],cd; int i,j,c,p,num=0,posite,allhc=0; char temp; printf(" 赫夫曼编码的应用 \n\n"); printf(" ○○○○○○○○○○○○○○○○○○○○○○○○○ "); printf("\n\n"); printf(" ●请输入字符串并以#号结束"); //scanf("%d",&n); /*输入叶子节点个数*/ /*----------循环接受字符-------------------*/ while((ch[num]=getchar())!='#'){ num++; } numbers=num; //得到字符个数----------------- huffmantree(huffnode); /*建立哈夫曼树*/ FILE *fp; if(!(fp=fopen("D:\\text1.txt","w"))) { printf("文件打开失败!"); } for(i=0;i<number;i++) /*该循环求每个叶子节点对应字符的哈夫曼编码*/ { cd.start=number-1;c=i; p=huffnode[c].parent; while(p!=-1) //逆向求叶子节点哈夫曼编码左0右1 { if(huffnode[p].lchild==c) cd.bit[cd.start]='0'; else cd.bit[cd.start]='1'; cd.start--;c=p; p=huffnode[c].parent; root=c; } //循环结束p指向根节点 for(j=cd.start+1;j<number;j++) /*保存求的每个叶节点的哈夫曼编码编码的起始位*/ { leafcode[i].bit[j]=cd.bit[j]; fputc(leafcode[i].bit[j],fp); } leafcode[i].start=cd.start; //leafcode[i].ch=huffnode[i].ch; } printf("\n"); printf(" --------------------------------------------------------------- \n"); printf("\n"); for(i=0;i<number;i++) /*输每个叶子节点的哈夫曼编码*/ { printf(" ☆字符:%c",huffnode[i].ch); printf(" 次数:%d",huffnode[i].weight); printf("\n"); printf(" ★'%c'字符的编码是:",huffnode[i].ch); for(j=leafcode[i].start+1;j<number;j++) printf("%c",leafcode[i].bit[j]); printf("\n"); } fclose(fp); printf("\n"); printf(" --------------------------------------------------------------- \n"); printf("\n"); printf(" ☆字符串被编码成为:"); if(!(fp=fopen("D:\\text1.txt","r"))) { printf("文件打开失败!"); } for(i=0;i<numbers;i++) /*所有字符的哈夫曼编码*/ { temp=ch[i]; posite=pos[(int)temp]; for(j=leafcode[posite].start+1;j<number;j++) { printf("%c",leafcode[posite].bit[j]); allHc[allhc]=leafcode[posite].bit[j]; allhc++; } } printf("\n\n"); printf(" --------------------------------------------------------------- \n"); printf("\n"); printf(" ★译的结果如下:"); unhanffman(huffnode); fclose(fp); }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值