首页 > 其他分享 >第二周

第二周

时间:2024-07-15 14:29:54浏览次数:7  
标签:解压 编码 结点 哈夫曼 字符 第二周 256

数据结构第二阶段综合应用算法训练自选题,我选择的是文件压缩解压。

一、问题描述

名称:基于哈夫曼编码的文件压缩解压

目的:利用哈夫曼编码压缩存储文件,节省空间

输入:任何格式的文件(压缩)或压缩文件(解压)

输出:压缩文件或解压后的原文件

功能:利用哈夫曼编码压缩解压文件

性能:快速

二、问题的初步讨论

为了建立哈夫曼树,首先扫描源文件,统计每类字符出现的频度(出现的次数),然后根据字符频度建立哈夫曼树,接着根据哈夫曼树生成哈夫曼编码。再次扫描文件,每次读取8bits,根据“字符—编码”表,匹配编码,并将编码存入压缩文件,同时存入编码表。解压时,读取编码表,然后读取编码匹配编码表找到对应字符,存入文件,完成解压。

三、总的UML协同图

clip_image001

四、文件读取方式和处理单元的分析

压缩解压的第一步就是读取文件,为了能够处理任何格式的文件,采用二进制方式读写文件。以一个无符号字符(unsigned char)的长度8位为处理单元,最多有256(0~255)种组合,即256类字符。

五、字符频度扫描的分析

要建立哈夫曼树,先要得到各类字符的频度,我想到了两种扫描方案:

1、利用链表存储,每扫描到一类新字符就动态分配内存;

2、利用数组,静态分配256个空间,对应256类字符,然后用下标随机存储。

链表在需要时才分配存储空间,可以节省内存,但是每加入一个新字符都要扫描一次链表,很费时;考虑到仅有256个字符种类,不是很多,使用静态数组,不会造成很大的空间浪费,而可以用数组的下标匹配字符,不需扫描数组就可以找到每类字符的位置,达到随机存储的目的,效率有很大的提高。当然,不一定每类字符都出现,所以,统计完后,需要排序,将字符频度为零的结点剔除。

我定义的数组类似这样:Node array[CHAR_KINDS],其中CHAR_KINDS为8位无符号字符对应的256(0~255)种不同组合,这样每扫描到一个字符,直接将字符作为下标,就可以找到字符的位置。

六、建立哈夫曼树的分析

哈夫曼树为二叉树,树结点含有权重(在这里为字符频度,同时也要把频度相关联的字符保存在结点中)、左右孩子、双亲等信息。

考虑到建立哈夫曼树所需结点会比较多,也比较大,如果静态分配,会浪费很大空间,故我们打算用动态分配的方法,并且,为了利用数组的随机访问特性,也将所需的所有树节点一次性动态分配,保证其内存的连续性。另外,结点中存储编码的域,由于长度不定,也动态分配内存。

6.1、这时,针对上面的字符扫描结点就要做一些改动

将其定义成临时结点TmpNode,这个结点仅保存字符及对应频度,也用动态分配,但是一次性分配256个空间,统计并将信息转移到树结点后,就将这256个空间释放,既利用了数组的随机访问,也避免了空间的浪费。

七、生成哈夫曼编码的分析

每类字符对应一串编码,故从叶子结点(字符所在结点)由下往上生成每类字符对应的编码,左‘0’,右‘1’。为了得到正向的编码,设置一个编码缓存数组,从后往前保存,然后从前往后拷贝到叶子结点对应编码域中,根据上面“建立哈夫曼树的协商”的约定,需要根据得到的编码长度为编码域分配空间。对于缓存数组的大小,由于字符种类最多为256种,构建的哈夫曼树最多有256个叶子结点,树的深度最大为255,故编码最长为255,所以分配256个空间,最后一位用于保存结束标志。

八、文件压缩的分析

上面协定以8位的字符为单元编码,这里压缩当然也以8位为处理单元。

首先将字符及种类和编码(编码表)存储于压缩文件中,供解压时使用。

然后以二进制打开源文件,每次读取一个8位的无符号字符,循环扫描匹配存储于哈夫曼树节点中的编码信息。

由于编码长度不定,故需要一个编码缓存,待编码满足8位时才写入,文件结束时缓存中可能不足8位,在后面补0,凑足8位写入,并将编码的长度随后存入文件。

在哈夫曼树节点中,编码的每一位都是以字符形式保存的,占用空间很大,不可以直接写入压缩文件,故需要转为二进制形式写入;至于如何实现,可以定义一个函数,将保存编码的字符数组转为二进制,但是比较麻烦,效率也不高;正好,可以利用C语言提供的位操作(与、或、移位)来实现,每匹配一位,用“或”操作存入低位,并左移一位,为下一位腾出空间,依次循环,满足8位就写入一次。

 

两个重要的结点结构体:

clip_image014

三个函数用于建立哈夫曼树和生成哈夫曼编码:

clip_image016

clip_image018

clip_image020

两个主要函数——压缩解压函数:

clip_image022

clip_image024

Select函数供CreateTree函数调用,找两个最小的结点,找到第一个后需要将其parent设为‘1’(初始化后为‘0’)表明此结点已被选中:

clip_image026

建立哈夫曼树,每次用select()函数找两个最小结点:

clip_image028

生成哈夫曼编码,由叶子到根反向生成编码,左‘0’,右‘1’,每个code域的内存动态分配:

clip_image030

 

     

标签:解压,编码,结点,哈夫曼,字符,第二周,256
From: https://www.cnblogs.com/kongxiangzeng/p/18303101

相关文章

  • 学Java的第二周(结构)
    条件结构1.顺序结构顺序结构是一组按照书写顺序执行的语句结构,这种语句结构的执行流程是按顺序地从一个处理过程转向下一个处理过程。2.选择结构选择结构又称为分支结构。当程序执行到分支判断的语句时,首先判断条件,然后根据条件表达式的结果选择相应的语句执行。分支结构包括......
  • java总结第二周
    本周对JAVA的while,switch,for以及数组进行了学习。数组是一种数据结构,它可以存储一系列相同类型的变量。在Java中,定义一个数组需要指定其数据类型和大小。数组的索引从0开始,最后一个元素的索引是数组长度减1。可以通过索引来访问和修改数组中的元素。数组的主要优点是可以方便地......
  • 小学期第二周总结(7.8-7.15)
    7.8周一小学期就没有周末这么一说了,所以周一跟周五在我看来没什么区别今天起晚了七点才起,看到表我一个鲤鱼打挺穿上衣服就走了饭都没吃好在时间是赶上了,我发现六年级真好教,上课我准备的那些没一会就讲完了,我让学生用我手机上的不背单词背单词,毕竟没有课本,又让他看了ted演讲,对英......
  • Java第二周学习总结
    深入Java基础语法本周,我进一步理解Java中的基本数据类型和引用数据类型。学会了如何根据需求选择合适的数据类型。掌握了算术运算符、关系运算符、逻辑运算符以及位运算符的使用,能够编写简单的表达式进行计算和条件判断。并深入学习了if-else、switch-case、for、while、do-whi......
  • 自学Java第二周
    本周学习一、Java能干些什么?1.共三个版本:JavaSE、JavaEE、JavaMEJavaSE:Java语言的(标准版),用于桌面应用开发,是其他两个版本的基础。JavaME:Java语言的(小型版),用于嵌入式电子设备或者小型移动设备。JavaEE:Java语言的(企业版),用于Web方向的网站开发(浏览器和服务器)。在这......
  • 2024暑假第二周总结
    运算符总结对字面量或者变量进行操作的符号算数运算符加减乘除取模取余加减乘publicclassyunsuanfu{publicstaticvoidmain(String[]args){//+System.out.println(3+2);//5//-System.out.println(3-2);//1//*......
  • Java学习第二周
    标识符是用来给变量,类,方法以及包进行命名的。标识符的命名规则1.必须以字母、下划线“”、美元符“$”开头。2.其他部分可以是字母、下划线“”、美元符“$”和数字的人员组合·。3.大小写敏感,且长度无限制。4.不可以是Java的关键字。标识符使用规范表示类名的标识符:每个单......
  • 小学期第二周个人总结
    本周,我投入了大量时间和精力来学习Hadoop生态系统的相关知识。Hadoop生态系统包括Hadoop、Hive和YARN等重要组件,它们在大数据处理和管理中发挥着关键作用。首先,我对Hadoop本身进行了深入了解。Hadoop是一个用于存储和处理大数据的开源框架,提供了分布式存储(HDFS)和分布式计算(MapRed......
  • 第二周总结
    1​下载JDK,安装JDK并配置环境变量。​阅读大道至简三至六章学习异常处理​理解类和对象​2.​下一周准备学习继承和多态,接口和抽象类3.困难:语法复杂:Java的语法规则相对较多,理解并记忆这些规则需要一定的时间和努力。编程逻辑难以理解:编程不仅仅是记忆语法,更重要的是理解......
  • 暑假第二周总结(7.9-7.13)
    这周做了什么学习了JAVA的基本内容通过实例认识了JAVA的面向对象编程及一些不同于C++面向对象的知识。时钟类packageClock;publicclassClock{privateDisplayhour=newDisplay(24);privateDisplayminute=newDisplay(60);publicvoidstart(){......