热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

哈夫曼编码压缩文件

#include#include#include#includeusingnamespacest

#include
#include
#include
#include
using namespace std;unsigned char saveChar = 0; //用来保存二进制文件,因为char类型是1个字节,所以每8位储存一次 ,而且用unsigned无符号型,避免符号位干扰
typedef struct
{int value;int p,l,r;
}HTNode,*HuffTree; //哈夫曼树struct fact //因为不是每一篇文章中所有字符都会出现
{ //所以结构体数组存储数组下标真正对应的字符ch以及权值weightchar ch;//字符int weight;//权重
};typedef char * * HuffCode; // 字符指针数组用于存储各个字符对应的编码
typedef char * CHAR;void select(HuffTree &HT,int n,int &s1,int &s2); //查找HT中未被使用的权值最小的两个点的下标
void CREATEHUFFTREE(HuffTree &HT,fact *ww,int n,HuffCode &HC); //建树函数,附带完成每一个字符对应的编码
void BecomeCode(HuffCode &HC,int n,CHAR &Code,char *Text,int *match); //由已知的各个字符的编码完成全文的编码void Code_ToBe_Artical(CHAR &Code,HuffTree &HT,fact *Fact,int n); //由全文的编码,用已经建立的哈弗曼树完成解码
int main()
{HuffTree HT&#61;NULL;HuffCode HC; //字符指针数组printf("请输入需要编码的文章\n");char Text[20000];CHAR Code &#61; NULL; //指针用于存储文章最终的编码gets(Text); //写入编码int len&#61;strlen(Text);//求出长度//写入文件FILE *fp&#61;fopen("E:\\demo.txt", "w");//printf("15555555");if(fputs(Text, fp)!&#61;EOF){printf("写入E:\\demo.txt文件成功,大小为 %dk",len/1024&#43;1);//printf("%d",len);}fclose(fp);int codeweight[54];//频率数组int match[54];memset(codeweight,0,sizeof(codeweight));//置0for(int i&#61;0;i<len;i&#43;&#43;) // 统计频率 空格下标为0 &#xff0c;&#xff08;A~Z&#xff09;下标分别为&#xff08;1~26&#xff09; &#xff08;a~z&#xff09;下标分别为&#xff08;27~52&#xff09;{if(Text[i]&#61;&#61;&#39; &#39;)codeweight[0]&#43;&#43;;else if(isupper(Text[i]))//若是大写字母codeweight[Text[i]-&#39;A&#39;&#43;1]&#43;&#43;;elsecodeweight[Text[i]-&#39;a&#39;&#43;27]&#43;&#43;;}int n&#61;0;fact Fact[54]; // 由于不是每一个字符都出现在文章中&#xff0c;将codeweight数组录入Fact结构体数组中for(int i&#61;0;i<&#61;52;i&#43;&#43;){if(codeweight[i]!&#61;0){if(i&#61;&#61;0)Fact[n].ch&#61;&#39; &#39;;else if(i<&#61;26) //转为相应的大写字母Fact[n].ch&#61;i&#43;&#39;A&#39;-1;elseFact[n].ch&#61;i&#43;&#39;a&#39;-27;//转为相应的小写字母match[i]&#61;n;Fact[n&#43;&#43;].weight&#61;codeweight[i];}}CREATEHUFFTREE(HT,Fact,n,HC); //建树函数&#xff0c;附带完成每一个字符对应的编码BecomeCode(HC,n,Code,Text,match); //由已知的各个字符的编码完成全文的编码Code_ToBe_Artical(Code,HT,Fact,n); //由全文的编码&#xff0c;用已经建立的哈弗曼树完成解码return 0;
}void select(HuffTree &HT,int n,int &s1,int &s2) //查找HT中未被使用的权值最小的两个点的下标
{s1&#61;s2&#61;0;HT[0].value&#61;0x7fffffff;for(int i&#61;1;i<&#61;n;i&#43;&#43;){if(HT[i].p!&#61;0)continue;if(HT[i].value<HT[s1].value)//比较权值{s2&#61;s1;s1&#61;i;}else if(HT[i].value<HT[s2].value)s2&#61;i;}
}void CREATEHUFFTREE(HuffTree &HT,fact *ww,int n,HuffCode &HC) //由已知的各个字符的编码完成全文的编码
{int m&#61;n*2-1;HT &#61; (HuffTree)malloc((m&#43;1)*sizeof(HTNode)); //分配m&#43;1个内存&#xff0c;是因为要存储m个数据&#xff0c;但是要从HT数组下标1开始int i,j,f;fact *w&#61;ww;HuffTree p;for(p &#61;HT,p&#43;&#43;,i&#61;1;i<&#61;n;i&#43;&#43;,p&#43;&#43;,w&#43;&#43;) //对HT &#xff08;1~n&#xff09;赋值语句{(*p).value&#61;(*w).weight,(*p).p&#61;0,(*p).l&#61;0,(*p).r&#61;0;}for(;i<&#61;m;i&#43;&#43;,p&#43;&#43;) //对HT &#xff08;n&#43;1~m&#xff09;赋值语句{(*p).value&#61;0,(*p).p&#61;0,(*p).l&#61;0,(*p).r&#61;0;}int s1,s2;for(i&#61;n&#43;1;i<&#61;m;i&#43;&#43;){select(HT,i-1,s1,s2);//查找最小的两个HT[s1].p&#61;i,HT[s2].p&#61;i;HT[i].l&#61;s1,HT[i].r&#61;s2;HT[i].value&#61;HT[s1].value&#43;HT[s2].value;}HC &#61; (HuffCode)malloc((n&#43;1)*sizeof(char *)); // 为字符指针数组分配内存char *temp&#61;(char *)malloc(n*sizeof(char));temp[n-1]&#61;&#39;\0&#39;;for(i&#61;1;i<&#61;n;i&#43;&#43;){int start&#61;n-2;for(j&#61;i,f&#61;HT[i].p;f!&#61;0;j&#61;f,f&#61;HT[f].p){if(HT[f].l&#61;&#61;j)temp[start--]&#61;&#39;0&#39;;elsetemp[start--]&#61;&#39;1&#39;;}HC[i]&#61;(char *)malloc((n-start)*sizeof(char));strcpy(HC[i],&temp[&#43;&#43;start]);}delete temp;printf("\n各个字符对应的编码\n");for(i&#61;1;i<&#61;n;i&#43;&#43;){if(ww[i-1].ch&#61;&#61;&#39; &#39;)printf("空格 --> ");elseprintf("%c --> ",ww[i-1].ch);puts(HC[i]);}
}void BecomeCode(HuffCode &HC,int n,CHAR &Code,char *Text,int *match) //由已知的各个字符的编码完成全文的编码
{int len,i; //纯粹是用已知的文本Text和HC将文本转化为编码len&#61;strlen(Text);Code &#61; (char *)malloc((len*n&#43;1)*sizeof(char));//初始化字符数组Code[0]&#61;&#39;\0&#39;; //置空for(i&#61;0;i<len;i&#43;&#43;){if(Text[i]&#61;&#61;&#39; &#39;)strcat(Code,HC[1]);else if(Text[i]<&#61;&#39;Z&#39;&&Text[i]>&#61;&#39;A&#39;)strcat(Code,HC[ match[Text[i]-&#39;A&#39;&#43;1]&#43;1 ]);elsestrcat(Code,HC[ match[Text[i]-&#39;a&#39;&#43;27]&#43;1 ]);}printf("\n文章编码为\n");puts(Code);FILE *fp&#61;fopen("E:\\test.txt", "w");if(fputs(Code, fp)!&#61;EOF){printf("文章编码写入E:\\test.txt文件成功\n");}fclose(fp);//进行压缩FILE *fp2&#61;fopen("E:\\test.txt", "r");FILE *fpw &#61; fopen("E:\\Huffman","wb");//2进制写入文件char reder;int Hufflength&#61;0;//压缩长度int num&#61;0;//计数//int t&#61;0;//printf("len&#61;%d\n",strlen(Code));// while ((reder&#61;fgetc(fp2))!&#61;EOF)//一个一个读入字符{//t&#43;&#43;;for(int i&#61;0;i<strlen(Code);i&#43;&#43;){//saveChar || &#61; (code[i]-&#39;0&#39;);//printf("%c",Code[i]);saveChar &#61; ((Code[i]-&#39;0&#39;)|saveChar);//让saveChar和编码中的每一位进行或操作num&#43;&#43;;if(num&#61;&#61;8){fwrite(&saveChar,sizeof(char),1,fpw);//每8位写入一次文件Hufflength&#43;&#43;;saveChar &#61; 0;//重新置0num &#61; 0;}else{saveChar &#61; saveChar << 1; //每做完一步&#xff0c;左移一位}}}//printf("t&#61;%d",t);//最后不到8位&#xff0c;移到最左端if(num !&#61; 8){saveChar &#61; saveChar<<(7-num);//移到最左端fwrite(&saveChar,sizeof(char),1,fpw);Hufflength&#43;&#43;;}printf("加密文件写入E:\\Huffman 成功,大小为 %dk",Hufflength/1024&#43;1);//printf("%d",Hufflength);fclose(fp2);fclose(fpw);}void Code_ToBe_Artical(CHAR &Code,HuffTree &HT,fact *Fact,int n) //根据哈夫曼编码解压缩,主要思想是根据编码遍历哈夫曼树
{printf("\n将编码解码\n");for(int i&#61;0;Code[i]!&#61;&#39;\0&#39;;i&#43;&#43;)//遍历哈夫曼编码{int m&#61;n*2-1,ok&#61;1;while(1){if(Code[i]&#61;&#61;&#39;0&#39;){m&#61;HT[m].l;if(HT[m].l&#61;&#61;0){printf("%c",Fact[m-1].ch);break;}}else if(Code[i]&#61;&#61;&#39;1&#39;){m&#61;HT[m].r;if(HT[m].r&#61;&#61;0){printf("%c",Fact[m-1].ch);ok&#61;0;}}if(!ok)break;i&#43;&#43;;}}printf("\n");return ;
}


推荐阅读
  • 本文介绍了使用哈夫曼树实现文件压缩和解压的方法。首先对数据结构课程设计中的代码进行了分析,包括使用时间调用、常量定义和统计文件中各个字符时相关的结构体。然后讨论了哈夫曼树的实现原理和算法。最后介绍了文件压缩和解压的具体步骤,包括字符统计、构建哈夫曼树、生成编码表、编码和解码过程。通过实例演示了文件压缩和解压的效果。本文的内容对于理解哈夫曼树的实现原理和应用具有一定的参考价值。 ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • IhaveconfiguredanactionforaremotenotificationwhenitarrivestomyiOsapp.Iwanttwodiff ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • [译]技术公司十年经验的职场生涯回顾
    本文是一位在技术公司工作十年的职场人士对自己职业生涯的总结回顾。她的职业规划与众不同,令人深思又有趣。其中涉及到的内容有机器学习、创新创业以及引用了女性主义者在TED演讲中的部分讲义。文章表达了对职业生涯的愿望和希望,认为人类有能力不断改善自己。 ... [详细]
  • 本文介绍了解决二叉树层序创建问题的方法。通过使用队列结构体和二叉树结构体,实现了入队和出队操作,并提供了判断队列是否为空的函数。详细介绍了解决该问题的步骤和流程。 ... [详细]
  • 本文介绍了游标的使用方法,并以一个水果供应商数据库为例进行了说明。首先创建了一个名为fruits的表,包含了水果的id、供应商id、名称和价格等字段。然后使用游标查询了水果的名称和价格,并将结果输出。最后对游标进行了关闭操作。通过本文可以了解到游标在数据库操作中的应用。 ... [详细]
  • 本文介绍了一个在线急等问题解决方法,即如何统计数据库中某个字段下的所有数据,并将结果显示在文本框里。作者提到了自己是一个菜鸟,希望能够得到帮助。作者使用的是ACCESS数据库,并且给出了一个例子,希望得到的结果是560。作者还提到自己已经尝试了使用"select sum(字段2) from 表名"的语句,得到的结果是650,但不知道如何得到560。希望能够得到解决方案。 ... [详细]
  • 本文介绍了南邮ctf-web的writeup,包括签到题和md5 collision。在CTF比赛和渗透测试中,可以通过查看源代码、代码注释、页面隐藏元素、超链接和HTTP响应头部来寻找flag或提示信息。利用PHP弱类型,可以发现md5('QNKCDZO')='0e830400451993494058024219903391'和md5('240610708')='0e462097431906509019562988736854'。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • Go GUIlxn/walk 学习3.菜单栏和工具栏的具体实现
    本文介绍了使用Go语言的GUI库lxn/walk实现菜单栏和工具栏的具体方法,包括消息窗口的产生、文件放置动作响应和提示框的应用。部分代码来自上一篇博客和lxn/walk官方示例。文章提供了学习GUI开发的实际案例和代码示例。 ... [详细]
  • Go语言实现堆排序的详细教程
    本文主要介绍了Go语言实现堆排序的详细教程,包括大根堆的定义和完全二叉树的概念。通过图解和算法描述,详细介绍了堆排序的实现过程。堆排序是一种效率很高的排序算法,时间复杂度为O(nlgn)。阅读本文大约需要15分钟。 ... [详细]
  • 本文介绍了在Win10上安装WinPythonHadoop的详细步骤,包括安装Python环境、安装JDK8、安装pyspark、安装Hadoop和Spark、设置环境变量、下载winutils.exe等。同时提醒注意Hadoop版本与pyspark版本的一致性,并建议重启电脑以确保安装成功。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • Oracle分析函数first_value()和last_value()的用法及原理
    本文介绍了Oracle分析函数first_value()和last_value()的用法和原理,以及在查询销售记录日期和部门中的应用。通过示例和解释,详细说明了first_value()和last_value()的功能和不同之处。同时,对于last_value()的结果出现不一样的情况进行了解释,并提供了理解last_value()默认统计范围的方法。该文对于使用Oracle分析函数的开发人员和数据库管理员具有参考价值。 ... [详细]
author-avatar
流丶血的卓洛
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有