哈夫曼树制作压缩软件 【此后无良辰】

哈夫曼树制作压缩软件

太爱bandzip了,在这里推荐这款压缩软件(我的是低仿
以下为自己软件图片
在这里插入图片描述

要求:

(1)压缩对象为外存任意格式任意位置的文件。
(2)运行时,压缩原文件的规模应不小于5K。运行后,外存上保留压缩后的文件。
(3)提供解压文件与原文件的相同性对比功能。
(4)建议,形成带交互界面功能的系统。
(5)其它要求同课后作业-01。提交时间待定。

一 :哈夫曼树是什么

哈夫曼树也称为最优二叉树,是加权路径长度最短的二叉树。
在这里插入图片描述
(a)树 WPL = 51 + 152 + 403 + 304 + 10*4 = 315

(b)树WPL = 53 + 153 + 402 + 302 + 10*2 = 220

通过比较发现,二叉树a的WPL值大于二叉树b,二叉树b其实就是一棵哈夫曼树。

二:哈夫曼树的构造

算法原理来自于贪心,
从有序的节点中
不断合并最小的二个节点再加入其中
在这里插入图片描述

三:哈夫曼编码

假若我们规定给每个结点的左路标记’0’,右路标记’1’,那么我们就可以用0、1来表示每个字母。以第一幅图中的二叉树b为例

在这里插入图片描述
四:文件压缩
在这里插入图片描述
(哈夫曼的介绍图片例子来自于csdn:Y-ANG,链接:https://blog.csdn.net/qq_33951180/article/details/53229240)

分界线---------------------------------------------------------------------分界线

在这里插入图片描述

正式开始

(默认已经安装了qt,没有见我qt计算器的分栏)

一 :了解以下知识(详情可见分栏)

如果我记得补上

1.qt的基础知识(详情见分栏qt的calculator)

2.文件流的读入和输出

		FILE *tem;
        strcpy(first_name,s.toLocal8Bit().data());
        tem=fopen(first_name,"rb");
        fclose(tem);
        

说明: 1. 使用"r"时,如果文件不存在,则出错。
2. 使用"w"时,如果没有文件,则创建一个新文件。
3. 使用"a"时,如果希望向文件尾添加数据,则该文件必须存在,否则出错。
4. “r+”,“w+”,"a+"都是可以输入和输出数据,但必须遵守上述3点

3.缓冲区

缓冲区又称为缓存,它是内存空间的一部分。也就是说,在内存空间中预留了一定的存储空间,这些存储空间用来缓冲输入或输出的数据,这部分预留的空间就叫做缓冲区。

4.字节的概念

64位编辑器
在这里插入图片描述
所以如果把文件作为二进制读入,然后用char储存,每个char字符就一个字节
8个二进制(这个很重要)

5.压缩和解压的概念

压缩相当于加密,解压相当于解密(其中改变了大小)

二 :代码部分

class类

class tree//haffman tree
{
    
    
        public :
        int times;//hez
        char data;//data
        int code;//字符
        int code_len;//字符长度
        tree *left_tree,*right_tree;
        tree(){
    
    times=code=code_len=0;data=NULL;left_tree=right_tree=0;}
        ~tree()
        {
    
    
                if(left_tree)
                delete left_tree;
                if(right_tree)
                delete right_tree;
        }
        void preoeder(int,int);//先序遍历,生成haffman编码
};

class haffman
{
    
    
        private:
        char first_name[100];//被压缩的名字(用来存路径)
        char final_name[100];//
        char code_name[100];//
        tree *bas[551];//基础字符编码树 
        tree *haff_root;//根节点
        int bas_len;//基础字符树个数
        char *buffer,*r;//缓冲区,读入文件内容
        int lenth;//读入内容长度
        int max_bu,bu;//最大缓冲区段基值,偏移量
        QString formulate;
        public :
        double origin_size,final_size;
        haffman()
        {
    
    
                haff_root=NULL;
                buffer = new char [10*1024*1024];//1m=1024kb 1kb=1024b;
                r= new char [10*1021*1024];
                memset(bas,0,sizeof(bas));
        }
        ~haffman()
        {
    
    
                delete buffer;
                delete r;
                delete haff_root;
        }
        void read(QString s);
        void count();//计算字符出现频率
        void new_sort(tree *a[],int,int);//快排
        void make_haffman();//生成haffman树
        void wbit(int);//向缓冲区写入一个字节
        void zip();
        void write(QString);//写入文件缓冲区中的内容
        void savecode();//保存haffman编码和缓冲区大小,供解压用
        void readbuffer(QString);//读入压缩文件内容到缓冲区
        void readcode();//读取haffman编码和缓冲区大小,供解压用
        void unzip(QString);
};

具体的函数实现有注释 但值得一提的是
缓冲区的数据可以写入被压缩的文件(这样就只会生成一个文件),也就是我们常用的压缩软件
本文的将其独立出来为.code为了真实的计算压缩之后和压缩之前的之比
(作业要求QAQ)
在这里插入图片描述
当然如果你有兴趣可以自己合并

代码放入github里面(现在放在码云了,国内好上去)

码云主页

ui界面

又到了拼乐高环节
在这里插入图片描述
详情参照qt的calculator

附录:因为最近有些朋友问了有些问题,我觉得还是很有必要再讲下一些需要注意的地方

1.读入为什么用char(因为它nb ),因为他可以储存许多奇奇怪怪的东西,例如他可以存数字和英文等等
2.建立树的过程 贪心思想,每次排序再选点然后建立
3.压缩 把每个原来的字符对应的二进制丢上去
例如 “aabb” “01011010”
这个时候,你打开压缩文件,肯定是一堆乱码(可能欧皇不是吧hhhhh)
因为假设你char八个二进制,电脑不一定有01011010对应的字符

最重要的一点 我有那么可怕吗
在这里插入图片描述
承包了我这个礼拜的笑点,哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_40493829/article/details/106531115