Qt实现哈夫曼编码解压缩软件详解

哈夫曼编码实训:使用Qt构建界面和简单的效率优化 前言 这篇博客主要是整理、记录一下这次数据结构实训的过程以及分享一些我个人的心得体会,当然,代码我个人的项目代码也会开源分享。先放链接:https://github.com/Melonl/FileCompress 相关资料以及开源代码 在上面给的Github链接里的Code&Ref文件夹下即是实训参考文档以及老师给的参考代码,main函数入口在Demo1.cpp里,Traini... 阅读详情


诸位既然点开了本帖,相信对此问题已有初步了解,哈夫曼树的原理不再赘述,我们开门见山,直入主题。

一、概要设计

问题拆解:设计一个基于哈夫曼编码的解压缩软件,这个问题我认为可以分解为以下几个子问题:

  • 读取传入文件,进行字符权重统计
  • 将出现的字符放入哈夫曼树结点,构建哈夫曼树,获取哈夫曼编码
  • 将编码相关信息写入压缩后的文件,再将传入文件的每个字符按照哈夫曼编码转换,每8个二进制位作为一个字节传入压缩后的文件
  • 解压部分:将传入的已压缩文件进行文件流读取,获取编码信息进行还原

根据这几个子问题的思路顺序,我们逐个击破,寻找解决方案:

  • 读取传入文件,需要用到文件流。这里推荐使用Qt自带的QFile文件流配以QDatastram辅助。因为,C++的文件流fstream无法识别中文路径(一说起这个,就想起Debug时的辛酸)。权重统计我用的是map记录:map<unsigned char ,int>Weightmap。
  • 哈夫曼结点的构造,和二叉树没有什么区别,只是在封装的struct里面加了unsigned char 型的字符,int型的权重,string型的哈夫曼编码,和是否是叶子结点的bool型标记(哈夫曼树叶子结点才是我们需要的编码)。将前面我们获取到的字符和权重加进去。
    我们将建立好的结点放入到一个vector内(理论上什么容器都可以),进入循环:根据哈夫曼结点的权重比较进行排序(直接调用sort),每次将连个最小的结点权重取出,相加得到权重和,以权重和建立一个新的结点,新结点的左右孩子结点就是这两个结点,将新结点加入到vector中,那两个结点删除。循环结束条件为vector内只剩下一个结点。这个结点便是哈夫曼树的根结点,保存一根结点足矣。
    我们从根结点出发遍历,左子树的string+“0”,右子树的string+“1”。并将unsigned char型的字符与这个string用map<unsigned char,string> PasswordMap 记录。
  • 传入辅助信息阶段:我们传入的信息有,PasswordMap.size(),循环传入PasswordMap->first(字符),PasswordMap->second.size()(记录编码长度),PasswordMap->second(这个字符串有可能超过8位,每个字节不足8位的部分补0)直到完全传入。另外一个方法是将所有字符与字符权重传入,在解压缩时再次构建哈夫曼树,两种思路我觉得都可以。这里我采用的第一种方法。
    传入哈夫曼编码阶段:遍历先前在读取文件时获取的字符串,将字符串的每一位转化为哈夫曼编码,用另一个字符串储存。这里不妨称这个字符串为二进制字符串,这个二进制字符串按8分割到最后可能会有不足8位的部分,对其进行补0操作。 最后再传入一个字节,记录补0数。
  • 解压部分:对应上部分的操作进行对应读取,主要思路是将压缩时传入的辅助信息提取,建立一个新的Map映射,根据这个映射,将原文件还原。

二:设计效果展示:

压缩前:
在这里插入图片描述
压缩中:
在这里插入图片描述
压缩后:
在这里插入图片描述
解压中:
在这里插入图片描述
解压后:
在这里插入图片描述

三、源代码

前面分析得很清晰,不过写代码的过程异常艰辛,充满了Debug时的汗水和泪水。
完整代码与封装好的可执行文件下载链接:https://gitee.com/sherlocknovitch/Qt_Compression
(可执行文件有58M,是因为封装了Qt的核心控件,去掉这些估计只有几百Kb的大小)
上代码:

1°MainWindow.h

先从窗口头文件看起,这块没有什么实质性的内容,只有几个槽函数(3个按钮的Click槽函数加一个让QprogressBar动起来的槽函数和一个出现文件打开错误情况时让QLineEdit清空的槽函数)
私有成员中QStirng path的作用是读取文件路径,作为压缩函数和解压缩函数的参数。
Compression* com是一个类指针,这个类是压缩类,在后面会提及。

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include"compression.h"
#include<QFileDialog>
#include<QMenu>
#include<QAction>


namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    void clear();
private slots:
    void on_pushButton_open_clicked();

    void on_pushButton_compression_clicked();

    void on_pushButton_decompression_clicked();

    void myslot(double per);

private:
    Ui::MainWindow *ui;
    Compression* com;
    QString path;
};

#endif // MAINWINDOW_H

2°MainWindow.cpp

这一块主要含义见注释即可,QProgressBar是Qt的一个控件,可以理解为进度条

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    resize(600,600);
    //设置窗口大小
    setWindowTitle("Sherlock's Compression");
    /设置窗口名称
    com=new Compression();
    //初始化压缩类指针
    connect(com,&Compression::error,this,&MainWindow::clear);
    //异常情况的信号接收
    connect(com,SIGNAL(mysignal(double)),this,SLOT(myslot(double)));
 
哈夫曼树,但图形化(数据结构课设cpp) 还在为哈夫曼树的课设而烦恼吗?看了这篇文章,从基础到进阶再到高级你都可以学会。确定不点进来吗😃 阅读详情

相关推荐

python如何开发解压及压缩软件工具

解压文件也类似,使用ZipFile()创建一个压缩文件对象,然后使用extractall()方法解压文件。解压文件也类似,使用open()创建一个压缩文件对象,然后使用extractall()方法解压文件。处理方式:zip是一种将多个文件压缩成一个文件的压缩方式,压缩后的文件可以通过许多不同的压缩软件进行解压,且不依赖于操作系统。而tar则是一种在Unix或类Unix操作系统中使用的打包文件的标准方法,压缩后的文件需要通过特定的解压软件进行解压。在某些情况下,tar格式的文件名可能会被截断或编码。

zhangzhechun的专栏 609

C++文件压缩实践:哈夫曼与游程编码技术

在信息技术飞速发展的当下,文件压缩技术作为减少数据存储空间和提高传输效率的重要手段,成为了每个IT专业人士不可或缺的技能之一。通过对文件进行压缩,可以减少存储介质的使用,降低网络传输时间,甚至对于某些特定文件类型,还能提高数据的保密性和安全性。游程编码(Run-Length Encoding, RLE)是一种简单的无损数据压缩算法,它将连续的数据块(称为“游程”)转换为一个计数和数据值的形式。游程编码特别适用于图像数据,尤其是那些包含大量连续像素的图像,如扫描得到的文档图像。

weixin_42600128的博客 599

C++ Qt实现的哈夫曼编码压缩解压工具,含可视化构建过程与频率统计

用标准C++和Qt 5/6开发的本地化文件压缩解压小工具,核心基于哈夫曼编码原理实现无损压缩。打开即用图形界面,支持拖拽或浏览选择任意文本文件,一键执行压缩或解压缩操作。过程中实时展示字符频次直方图、哈夫曼树动态构建步骤(含节点合并动画逻辑)、编码表生成结果及最终压缩率数值(如原始大小/压缩后大小/节省百分比)。所有算法封装在huffman.h和compression.h中,树结构完全手写,不调用STL容器以外的第三方代码;GUI由mainwindow.ui定义,信号槽连接清晰,交互响应及时。项目已配置好c

ansible6ops的博客 227

基于哈夫曼树的文件压缩和解压(QT可视化界面)

大二课设作业。使用哈夫曼树进行文件编码,从而实现文件的压缩。整个程序基于QT5.12进行操作,并且实现了可视化界面。包括编码,解码。如果有什么问题,可私戳了解。

信息论:利用C++利用哈夫曼编码技术对文本进行压缩

本文要设计一款简单的压缩软件,具有简单的操作界面,对文本进行等长或变长压缩;针对这些要求,本文设计并开发了3个小的模块来实现相关功能。由于技术有限,未能将三个模块进行整合。其中变长压缩运用了Huffman编码,Huffman 编码是一种经典的变长压缩编码。根据大数据统计出的字母出现概率,Huffman 编码将各个字母按照不同码长进行编码,用短码表示出现概率高的字母,用长码表示出现概率低的字母,从而使得所有字母的平均码长降低,达到压缩的目的。

ESP32S3学习——i2c,点亮0.96寸oled

ESP32S3学习——i2c,点亮0.96寸oled

HandBAI的博客 1万+

基于FPGA的DDR学习——1.基础知识

⚪DDR2(Double Data Rate2)SDRAM是由JEDEC(电子设备工程联合委员会)开发的第三代SDRAM内存技术标准,1.8V工作电压,240线接口,提供了相较于DDR SDRAM更高的运行效能与更低的电压,同样采用在时钟的上升/下降沿同时进行数据传输的基本方式,但拥有两倍于上一代DDR内存预读取能力(即4bit数据预取能力),其常见的频率规范有DDR2 400\533\667\800\1066\1333等,总线频率553MHZ的DDR2内存只需133MHZ的工作频率。

qq_44932488的博客 2069

蜗牛星际+OpenWrt实战:双网口变AP模式,让所有设备同网段互通

本文详细介绍了如何将蜗牛星际双网口小主机刷入OpenWrt系统,并将其配置为AP模式,实现与主路由同网段的无缝桥接。通过关闭DHCP、桥接物理网口等核心步骤,解决家庭网络设备割裂问题,让所有设备在同一局域网内高效互通,特别适合追求网络简洁和厌恶多级NAT的技术爱好者。

zero1的博客 959

Paraview:Python Calculator Filter

python calculator过滤器 from paraview.simple import * connection = servermanager.Connect('localhost',11111) er = servermanager.sources.EnSightreader(CaseFileName='/.../data.case') er.PointArrays = ['x_velocity','1','y_velocity','1','z_velocity','1','cp','1']

haimianjie2012的专栏 3495

生产实习-实习报告-Raspberry Pi的应用

生产实习-Raspberry Pi的应用 一.设计任务: 1、搭建树莓派开发环境 主要包括烧录树莓派操作系统,远程访问树莓派,树莓派接口配置以及树莓派与windows实现文件共享等。 2、树莓派的基本操作 控制GPIO点亮LED灯以及树莓派舵机云台控制 3、安装OpenCV及图像采集实验 OpenCV配合树莓派,直接读取来自树莓派摄像头Pi Camera的视频,进行人脸识别、边缘检测、颜色判别等各种计算机视觉开发。 4、树莓派小车远程Wi-Fi控制 使用树莓派驱动L298N,用树莓派板载Wi-Fi控制

青竹小轩的博客 750

【常见开源库的二次开发】基于openssl的加密与解密——openssl认识与配置(一)

OpenSSL 是一个开源的软件库,它提供了一系列加密工具和协议,主要用于实现安全通信,如在网络上的数据传输。它支持多种加密算法,包括对称加密、非对称加密、散列函数、伪随机数生成器、数字签名、密钥交换以及证书管理等。

嵌入式技术开发 4160

【SWAT】SWAT中预定义河网及流域

平原圩区没有明显的海拔差异。DEM中包含的地形信息无法定义河段的位置和水文连接,SWAT模型Watershed Delineator中提供两种方法,帮助用户输入流域拓扑信息。第一种方法,“Burn-in”和手动绘制河段和子流域边界。首先,使用“Burn-in”功能导入数字河道网络(DCN),并根据DEM和DCN绘制河流和子流域。然后在ArcGIS中编辑“流域”和“河段”层,可以调整位置、范围和水文连接。第二种方法,可以手动绘制或重新编辑河流和子流域,预定义河网及流域。

```On Earth, Be Water, By Coding``` 3273

【AUTOSAR-E2E】-1.4-详述E2E Transformer解决方案

共13页精讲 目录 1“Data Transformation”介绍 1.1 基于SOME/IP Transformer 1.2 基于COM Based Transformer 2 ComXf(COM Based Transformer)介绍 2.1 ComXf(COM Based Transformer)功能规范 2.2 ComXf(COM Based Transformer)提供的服务 2.3 配置注意事项 3 E2EXf(E2E Transformer)介绍 3.1 E2EX...

「汽车电子助手」的博客 4700

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

上一篇: 【数据结构】实验报告11 将二叉树后序线索化并进行后序遍历
下一篇: 【数据结构】实验报告12 输出有向无环图的所有拓扑序列
RealWeakCoder
博客等级 码龄7年 236粉丝 68原创
评论 30
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值