C++写利用Huffman编码实现文件的压缩与解压缩,要求能够测试压缩率和解压缩速度

时间: 2024-03-27 11:38:00 浏览: 15
好的,我可以帮你回答这个问题。首先,Huffman编码是一种无损数据压缩算法,它可以将一些出现频率较高的字符用较短的编码表示,从而达到压缩数据的目的。下面是一些实现Huffman编码的基本步骤: 1. 统计字符出现频率,生成Huffman树。 2. 根据Huffman树生成编码表。 3. 将编码表写入压缩文件头部。 4. 读取原文件,将每个字符转换为对应的Huffman编码,并写入输出文件。 5. 解压缩时,读取压缩文件头部的编码表,根据编码表将Huffman编码转换为字符。 下面是一个用C++实现Huffman编码压缩和解压缩的示例代码: ```cpp #include <iostream> #include <fstream> #include <queue> #include <unordered_map> #include <vector> #include <bitset> #include <ctime> using namespace std; // Huffman树节点 struct HuffmanNode { char ch; int freq; HuffmanNode *left, *right; HuffmanNode(char ch, int freq) : ch(ch), freq(freq), left(nullptr), right(nullptr) {} }; // 比较函数,用于构建Huffman树 struct Compare { bool operator()(const HuffmanNode* a, const HuffmanNode* b) const { return a->freq > b->freq; } }; // 统计字符出现频率 unordered_map<char, int> getCharFreq(const string& input) { unordered_map<char, int> freq; for (char ch : input) { ++freq[ch]; } return freq; } // 构建Huffman树 HuffmanNode* buildHuffmanTree(const unordered_map<char, int>& freqMap) { priority_queue<HuffmanNode*, vector<HuffmanNode*>, Compare> pq; for (auto& item : freqMap) { pq.push(new HuffmanNode(item.first, item.second)); } while (pq.size() > 1) { HuffmanNode* left = pq.top(); pq.pop(); HuffmanNode* right = pq.top(); pq.pop(); HuffmanNode* parent = new HuffmanNode('\0', left->freq + right->freq); parent->left = left; parent->right = right; pq.push(parent); } return pq.top(); } // 生成编码表 void generateEncodingTable(HuffmanNode* root, unordered_map<char, string>& encodingTable, string code) { if (!root) return; if (root->ch != '\0') { encodingTable[root->ch] = code; } generateEncodingTable(root->left, encodingTable, code + "0"); generateEncodingTable(root->right, encodingTable, code + "1"); } // 编码 string encode(const string& input, const unordered_map<char, string>& encodingTable) { string encoded; for (char ch : input) { encoded += encodingTable.at(ch); } return encoded; } // 解码 string decode(const string& encoded, HuffmanNode* root) { string decoded; HuffmanNode* node = root; for (char bit : encoded) { if (bit == '0') { node = node->left; } else { node = node->right; } if (node->ch != '\0') { decoded += node->ch; node = root; } } return decoded; } // 将编码表写入文件头部 void writeEncodingTable(const unordered_map<char, string>& encodingTable, ofstream& outfile) { for (auto& item : encodingTable) { outfile << item.first << item.second << endl; } } // 从文件头部读取编码表 unordered_map<string, char> readEncodingTable(ifstream& infile) { unordered_map<string, char> encodingTable; string line; while (getline(infile, line)) { char ch = line[0]; string code = line.substr(1); encodingTable[code] = ch; } return encodingTable; } // 压缩文件 void compressFile(const string& inputFilename, const string& outputFilename) { // 读取原文件 ifstream infile(inputFilename, ios::in | ios::binary); if (!infile) { cerr << "Failed to open input file " << inputFilename << endl; return; } string input((istreambuf_iterator<char>(infile)), istreambuf_iterator<char>()); infile.close(); // 统计字符出现频率 unordered_map<char, int> freqMap = getCharFreq(input); // 构建Huffman树 HuffmanNode* root = buildHuffmanTree(freqMap); // 生成编码表 unordered_map<char, string> encodingTable; generateEncodingTable(root, encodingTable, ""); // 将编码表写入文件头部 ofstream outfile(outputFilename, ios::out | ios::binary); if (!outfile) { cerr << "Failed to open output file " << outputFilename << endl; return; } writeEncodingTable(encodingTable, outfile); // 编码并写入输出文件 string encoded = encode(input, encodingTable); int padding = 8 - (encoded.size() % 8); string paddingStr(padding, '0'); outfile << paddingStr << encoded; outfile.close(); } // 解压缩文件 void decompressFile(const string& inputFilename, const string& outputFilename) { // 读取压缩文件头部的编码表 ifstream infile(inputFilename, ios::in | ios::binary); if (!infile) { cerr << "Failed to open input file " << inputFilename << endl; return; } unordered_map<string, char> encodingTable = readEncodingTable(infile); // 读取压缩文件内容 string encoded((istreambuf_iterator<char>(infile)), istreambuf_iterator<char>()); infile.close(); // 解码 int padding = stoi(encoded.substr(0, 8), nullptr, 2); string decoded = decode(encoded.substr(8), buildHuffmanTree(encodingTable), padding); // 写入输出文件 ofstream outfile(outputFilename, ios::out | ios::binary); if (!outfile) { cerr << "Failed to open output file " << outputFilename << endl; return; } outfile << decoded; outfile.close(); } int main() { string inputFilename = "input.txt"; string compressedFilename = "compressed.bin"; string decompressedFilename = "decompressed.txt"; // 压缩文件 clock_t start = clock(); compressFile(inputFilename, compressedFilename); clock_t end = clock(); cout << "Compressed file created." << endl; cout << "Compression time: " << (double)(end - start) / CLOCKS_PER_SEC << " seconds." << endl; // 解压缩文件 start = clock(); decompressFile(compressedFilename, decompressedFilename); end = clock(); cout << "Decompressed file created." << endl; cout << "Decompression time: " << (double)(end - start) / CLOCKS_PER_SEC << " seconds." << endl; // 计算压缩率 ifstream infile(inputFilename, ios::in | ios::binary); long long inputFileSize = infile.seekg(0, ios::end).tellg(); infile.close(); ifstream compressedFile(compressedFilename, ios::in | ios::binary); long long compressedFileSize = compressedFile.seekg(0, ios::end).tellg(); compressedFile.close(); double compressionRatio = (double)compressedFileSize / inputFileSize; cout << "Compression ratio: " << compressionRatio * 100 << "%" << endl; return 0; } ``` 在上面的示例代码中,我们用了一个简单的文本文件作为输入文件,使用了`ifstream`和`ofstream`来读写文件。我们还用了`clock`函数来计算压缩和解压缩文件所需的时间,以及计算压缩率。

相关推荐

最新推荐

recommend-type

数据结构课程设计-基于Huffman编码的文件压缩与解压缩.docx

数据结构课程设计-基于Huffman编码的文件压缩与解压缩 2.2.1结构设计 typedef struct Node { unsigned char ch;//字符 double weight;//字符的频数 int parent,lchild,rchild; }HTNode,HuffmanTree[2*N-1];//...
recommend-type

用Huffman编码实现文件压缩(含代码)

用数据结构的Huffman编码来实现对文件进行压缩,是北邮数据结构的大作业!
recommend-type

huffman具体的压缩及解压缩过程及程序

摘要:哈夫曼编码作为一种最常用无损压缩编码方法,在数据压缩程序中具有非常...本文对哈夫曼编码算法进行了全面的探讨,给出了具体的压缩及解压缩过程及程序,并结合数字图像的特点对绘出的算法讨论,提出一些改进。
recommend-type

二值图像的像元分组及Huffman压缩/解压 数据结构实习

vc2010编译通过 二值图像的象元分组 软件压缩/解压缩软件 Szip(Huffman算法及应用)
recommend-type

zigbee-cluster-library-specification

最新的zigbee-cluster-library-specification说明文档。
recommend-type

管理建模和仿真的文件

管理Boualem Benatallah引用此版本:布阿利姆·贝纳塔拉。管理建模和仿真。约瑟夫-傅立叶大学-格勒诺布尔第一大学,1996年。法语。NNT:电话:00345357HAL ID:电话:00345357https://theses.hal.science/tel-003453572008年12月9日提交HAL是一个多学科的开放存取档案馆,用于存放和传播科学研究论文,无论它们是否被公开。论文可以来自法国或国外的教学和研究机构,也可以来自公共或私人研究中心。L’archive ouverte pluridisciplinaire
recommend-type

实现实时数据湖架构:Kafka与Hive集成

![实现实时数据湖架构:Kafka与Hive集成](https://img-blog.csdnimg.cn/img_convert/10eb2e6972b3b6086286fc64c0b3ee41.jpeg) # 1. 实时数据湖架构概述** 实时数据湖是一种现代数据管理架构,它允许企业以低延迟的方式收集、存储和处理大量数据。与传统数据仓库不同,实时数据湖不依赖于预先定义的模式,而是采用灵活的架构,可以处理各种数据类型和格式。这种架构为企业提供了以下优势: - **实时洞察:**实时数据湖允许企业访问最新的数据,从而做出更明智的决策。 - **数据民主化:**实时数据湖使各种利益相关者都可
recommend-type

用 Python 画一个可以动的爱心

好的,我可以帮助您使用Python来绘制一个动态的爱心。您可以使用turtle库来实现。以下是实现代码: ```python import turtle import math # 设置画布和画笔 canvas = turtle.Screen() canvas.bgcolor("black") pencil = turtle.Turtle() pencil.speed(0) pencil.color("red", "pink") pencil.pensize(3) # 定义爱心函数 def draw_love(heart_size, x_offset=0, y_offset=0):
recommend-type

JSBSim Reference Manual

JSBSim参考手册,其中包含JSBSim简介,JSBSim配置文件xml的编写语法,编程手册以及一些应用实例等。其中有部分内容还没有写完,估计有生之年很难看到完整版了,但是内容还是很有参考价值的。
recommend-type

"互动学习:行动中的多样性与论文攻读经历"

多样性她- 事实上SCI NCES你的时间表ECOLEDO C Tora SC和NCESPOUR l’Ingén学习互动,互动学习以行动为中心的强化学习学会互动,互动学习,以行动为中心的强化学习计算机科学博士论文于2021年9月28日在Villeneuve d'Asq公开支持马修·瑟林评审团主席法布里斯·勒菲弗尔阿维尼翁大学教授论文指导奥利维尔·皮耶昆谷歌研究教授:智囊团论文联合主任菲利普·普雷教授,大学。里尔/CRISTAL/因里亚报告员奥利维耶·西格德索邦大学报告员卢多维奇·德诺耶教授,Facebook /索邦大学审查员越南圣迈IMT Atlantic高级讲师邀请弗洛里安·斯特鲁布博士,Deepmind对于那些及时看到自己错误的人...3谢谢你首先,我要感谢我的两位博士生导师Olivier和Philippe。奥利维尔,"站在巨人的肩膀上"这句话对你来说完全有意义了。从科学上讲,你知道在这篇论文的(许多)错误中,你是我可以依