[置顶] 哈夫曼编码应用之实现文件压缩
2016-07-30 00:35
363 查看
背景:为了锻炼自己的代码能力,以及数据结构算法掌握的能力,做此项目来锻炼自己提高自己的能力,本项目运用了C++中的知识,比如模板类,仿函数等等,还用到了数据结构中的算法知识,比如建堆调堆、哈夫曼编码,还用到了文件操作的知识。总是试一次很好的训练。
介绍一下哈夫曼编码:
哈夫曼编码(Huffman Coding)是一种编码方式,哈夫曼编码是可变字长编码(VLC)的一种。Huffman于1952年提出一种编码方法,该方法完全依据字符出现概率来构造异字头的平均长 度最短的码字,有时称之为最佳编码,一般就叫作Huffman编码。
下面列出实现文件压缩的C++代码:
建堆调堆头文件:Heap.h
建堆调堆实现文件:Heap.hpp
建立哈夫曼数头文件:HuffmanTree.h
建立哈夫曼数实现文件:HuffmanTree.hpp
文件压缩头文件:FileCompress.h
文件压缩实现文件:FileCompreess.cpp
测试代码:压缩测试函数,放在主函数里
测试代码:解压缩测试函数,放在主函数里
主函数:test.cpp
现在测试的是我桌面上的一个文件:文件名为:input.txt
![](http://img.blog.csdn.net/20160730002844729?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
压缩过程
![](http://img.blog.csdn.net/20160730002943739?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
压缩和解压缩之后桌面显示:
![](http://img.blog.csdn.net/20160730003058638?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
解压缩文件:input_Com.txt
![](http://img.blog.csdn.net/20160730003309506?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
本项目特点:将压缩后的文件,以及配置文件新建立了一个文件夹,放在文件夹中,这样美观,易识别。
代码中还有很多不足,有些问题也未解决,欢迎各位批评指正!!! 我也会子啊后续努力中继续添加功能!
介绍一下哈夫曼编码:
哈夫曼编码(Huffman Coding)是一种编码方式,哈夫曼编码是可变字长编码(VLC)的一种。Huffman于1952年提出一种编码方法,该方法完全依据字符出现概率来构造异字头的平均长 度最短的码字,有时称之为最佳编码,一般就叫作Huffman编码。
下面列出实现文件压缩的C++代码:
建堆调堆头文件:Heap.h
#ifndef __HEAP_H__ #define __HEAP_H__ #include <iostream> #include <assert.h> #include <vector> #include "FileCompress.h" #include "HuffmanTree.h" template <typename T> struct Less { bool operator()(const T& left, const T& right)const { return left < right; } }; template<typename K> //模板的偏特化 struct Less<HuffmanNode<K>*> { bool operator()(const HuffmanNode<K>* left, const HuffmanNode<K>* right)const { return left->_weight < right->_weight; } }; //template <> //struct Less<CharInfo> //{ // bool operator()(const CharInfo& left, const CharInfo& right)const // { // return left < right; // } //}; template <typename T> struct Greater { bool operator()(const T& left, const T& right)const { return left > right; } }; template <typename T,template<class> class Compare = Greater> class Heap { friend std::ostream& operator<<<T,Compare>(std::ostream& out, const Heap<T,Compare>& heap); public: Heap(); Heap(const T* array, size_t size); Heap(const Heap<T,Compare>& heap); Heap<T,Compare>& operator=(const Heap<T, Compare>& heap); ~Heap(); void Push(const T& x); void Pop(); T Top()const; bool Empty()const; size_t Size()const; protected: void _AdjustDown(int parent); void _AdjustUp(int pos); protected: std::vector<T> _array; }; //堆排序 template <typename T, template<class> class Compare = Greater> void HeapSort(T* array, size_t size, const Compare<T>& com = Compare<T>()); //建初堆 template <typename T, template<class> class Compare = Greater> void CrtHeap(T* array, size_t size, const Compare<T>& com = Compare<T>()); //下调 template <typename T, template<class> class Compare = Greater> void AdjustDown(T* array, size_t size, int parent = 0, const Compare<T>& com = Compare<T>()); template <typename T, template<class> class Compare = Greater> std::ostream& operator<<(std::ostream& out, const Heap<T, Compare>& heap); template <typename T, template<class> class Compare = Greater> void GetTopK(T* array, const vector<T>& money, const size_t& k, const size_t& n, const Compare<T>& com = Compare<T>()); #endif /*__HEAP_H__*/
建堆调堆实现文件:Heap.hpp
#define _CRT_SECURE_NO_WARNINGS 1 #include "Heap.h" template <typename T,template<class> class Compare> Heap<T,Compare>::Heap() {} template <typename T,template<class> class Compare> Heap<T,Compare>::~Heap() {} template <typename T,template<class> class Compare> Heap<T,Compare>::Heap(const T* array, size_t size) { this->_array.resize(size); for (size_t i = 0; i < size; ++i) { this->_array[i] = array[i]; } for (int i = (size - 2) / 2; i >= 0; --i) { this->_AdjustDown(i); } } template <typename T,template<class> class Compare> Heap<T,Compare>::Heap(const Heap<T,Compare>& heap) { size_t size = heap.size(); this->_array.resize(size); for (size_t i = 0; i < size; ++i) { this->_array[i] = heap._array[i]; } } template <typename T,template<class> class Compare> Heap<T,Compare>& Heap<T,Compare>::operator=(const Heap<T,Compare>& heap) { if (this != &heap) { this->_array = heap._array; } return *this; } template <typename T,template<class> class Compare> void Heap<T,Compare>::Push(const T& x) { size_t size = this->_array.size(); this->_array.push_back(x); this->_AdjustUp(size); } //Compare template <typename T,template<class> class Compare> void Heap<T,Compare>::_AdjustUp(int pos) { assert(pos<this->_array.size()); Compare<T> com; int parent = (pos - 1) / 2; int child = pos; while (parent >= 0 && com(this->_array[child], this->_array[parent])) { swap(this->_array[child], this->_array[parent]); child = parent; parent = (child - 1) / 2; } } template <typename T,template<class> class Compare> void Heap<T,Compare>::Pop() { assert(!this->_array.empty()); size_t size = this->_array.size(); swap(this->_array[0], this->_array[size - 1]); this->_array.pop_back(); this->_AdjustDown(0); } //Compare template <typename T,template<class> class Compare> void Heap<T,Compare>::_AdjustDown(int parent) { size_t child = parent * 2 + 1; size_t size = this->_array.size(); Compare<T> com; while (child < size) { if (child + 1 < size && com(this->_array[child + 1], this->_array[child])) { ++child; } if (com(this->_array[child], this->_array[parent])) { swap(this->_array[parent], this->_array[child]); parent = child; child = parent * 2 + 1; } else { break; } } } template <typename T,template<class> class Compare> T Heap<T,Compare>::Top()const { assert(!this->_array.empty()); return this->_array[0]; } template <typename T,template<class> class Compare> bool Heap<T,Compare>::Empty()const { return this->_array.empty(); } template <typename T,template<class> class Compare> size_t Heap<T,Compare>::Size()const { return this->_array.size(); } template <typename T,template<class> class Compare> std::ostream& operator<<(std::ostream& out, const Heap<T,Compare>& heap) { size_t size = heap._array.size(); for (size_t i = 0; i < size; ++i) { out << heap._array[i] << " "; } out << endl; return out; } //堆排序 //template <typename T> //void HeapSort(T* array, size_t size) //{ // //建初堆 // Heap<T,Compare> heap(array, size); // for (int i = size - 1; i >= 0; --i) // { // array[i] = heap.GetTop(); // heap.Pop(); // } //} template <typename T,template<class> class Compare> void HeapSort(T* array, size_t size, const Compare<T>& com) { CrtHeap(array, size, com);//建初堆 for (int i = size - 1; i > 0; --i) { swap(array[0], array[i]); //交换头和尾 AdjustDown(array, i, 0, com); //使得0...i-1也为堆 } } //建初堆 template <typename T, template<class> class Compare> void CrtHeap(T* array, size_t size, const Compare<T>& com) { int parent = (size - 2) / 2; for (int i = parent; i >= 0; --i) { AdjustDown(array, size, i, com); } } //下调 //Compare template <typename T,template<class> class Compare> void AdjustDown(T* array, size_t size, int parent, const Compare<T>& com) { int child = parent * 2 + 1; while (child < (int)size) { if (child + 1 < size && com(array[child + 1], array[child])) { ++child; } if (com(array[child], array[parent])) { swap(array[parent], array[child]); parent = child; child = parent * 2 + 1; } else { break; } } } template <typename T, template<class> class Compare> void GetTopK(T* array, const vector<T>& money, const size_t& k, const size_t& n, const Compare<T>& com) { assert(array); assert(k < n); for (size_t i = 0; i < k; ++i) { array[i] = money[i]; } //建堆 for (int i = (k - 2) / 2; i >= 0; --i) { AdjustDown(array, k, i, com); } for (int i = k; i < n; ++i) { if (com(array[0],money[i])) { array[0] = money[i]; AdjustDown(array, k, 0, com); } } }
建立哈夫曼数头文件:HuffmanTree.h
#pragma once #ifndef __HUFFMAN_TREE_H__ #define __HUFFMAN_TREE_H__ #include <iostream> template <typename T> struct HuffmanNode { T _weight; HuffmanNode* _left; HuffmanNode* _right; HuffmanNode(T weight = 0) :_weight(weight), _left(NULL), _right(NULL) {} //建堆时要用 //bool operator<(const HuffmanNode* right) //{ // return this->_weight < right->_weight; //} }; template <typename T> class HuffmanTree { typedef HuffmanNode<T> Node; public: HuffmanTree(); HuffmanTree(const T* array, size_t size, int vailed = 0); Node* GetHuffmanNode(); ~HuffmanTree(); protected: static Node* _CreateHuffmanTree(const T* array, size_t size, int vailed = 0); static void _Clear(Node* root); protected: Node* _root; }; #endif /*__HUFFMAN_TREE_H__*/
建立哈夫曼数实现文件:HuffmanTree.hpp
#pragma once #ifndef __HUFFMAN_TREE_HPP__ #define __HUFFMAN_TREE_HPP__ #include "Heap.hpp" #include "HuffmanTree.h" template <typename T> HuffmanTree<T>::HuffmanTree() :_root(NULL) {} template <typename T> HuffmanTree<T>::HuffmanTree(const T* array, size_t size, int vailed) : _root(NULL) { this->_root = _CreateHuffmanTree(array, size, vailed); } template <typename T> HuffmanNode<T>* HuffmanTree<T>::_CreateHuffmanTree(const T* array, size_t size, int valid) { //选最小,减小堆 Heap<Node*, Less> heap; Node* parent = NULL; for (size_t i = 0; i < size; ++i)//往堆里入结点 { if (array[i] != valid) { heap.Push(new Node(array[i])); } } while (heap.Size() > 1) { Node* minFirst = heap.Top(); heap.Pop(); Node* minSecond = heap.Top(); heap.Pop(); parent = new Node(minFirst->_weight + minSecond->_weight); parent->_left = minFirst; parent->_right = minSecond; heap.Push(parent); } return parent; } template <typename T> HuffmanTree<T>::~HuffmanTree() { this->_Clear(this->_root); } template <typename T> void HuffmanTree<T>::_Clear(Node* root) { if (root) { _Clear(root->_left); _Clear(root->_right); delete root; } } template <typename T> HuffmanNode<T>* HuffmanTree<T>::GetHuffmanNode() { return this->_root; } #endif /*__HUFFMAN_TREE_HPP__*/
文件压缩头文件:FileCompress.h
#pragma once #ifndef __HUFFMAN_CODE_H__ #define __HUFFMAN_CODE_H__ #include <iostream> #include <vector> #include <string> #include "HuffmanTree.h" using namespace std; typedef unsigned long long TypeLong; struct CharInfo { unsigned char _ch; //字符 TypeLong _count;//出现次数 string _code;//Huffman编码 CharInfo(TypeLong count = 0) :_ch(0), _count(count) {} bool operator!=(const CharInfo& info)const { return this->_count != info._count; } bool operator<(const CharInfo& info)const { return this->_count < info._count; } CharInfo operator+(const CharInfo& info)const { return CharInfo(this->_count + info._count); } }; class FileCompress { public: FileCompress(); void CompressHuffCode(const char* filename); void UnCompressHuffCode(const char* filename); void PrintCode()const; protected: static void GenerateHuffmanCode(HuffmanNode<CharInfo>* root, FileCompress& file, string& code); protected: CharInfo _info[256]; }; #endif /*__HUFFMAN_CODE_H__*/
文件压缩实现文件:FileCompreess.cpp
#define _CRT_SECURE_NO_WARNINGS 1 #include <assert.h> #include "FileCompress.h" #include <io.h> #include <direct.h> #define __DEBUG_COUT__ FileCompress::FileCompress() { <span style="white-space:pre"> </span>size_t size = sizeof(this->_info) / sizeof(this->_info[0]); <span style="white-space:pre"> </span>for (size_t i = 0; i < size; ++i) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>this->_info[i]._ch = i; <span style="white-space:pre"> </span>this->_info[i]._count = 0; <span style="white-space:pre"> </span>} } void FileCompress::CompressHuffCode(const char* filename) { <span style="white-space:pre"> </span>assert(filename); <span style="white-space:pre"> </span>FILE* fOut = fopen(filename, "rb"); <span style="white-space:pre"> </span>assert(fOut); <span style="white-space:pre"> </span>//统计字符出现的次数 <span style="white-space:pre"> </span>unsigned char ch = fgetc(fOut); <span style="white-space:pre"> </span>while (!feof(fOut)) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>++this->_info[(unsigned char)ch]._count; <span style="white-space:pre"> </span>ch = fgetc(fOut); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>fseek(fOut, 0, SEEK_SET); <span style="white-space:pre"> </span>//建立哈夫曼树 <span style="white-space:pre"> </span>HuffmanTree<CharInfo> huffTree(this->_info, sizeof(this->_info) / sizeof(this->_info[0]), 0); <span style="white-space:pre"> </span>//生成哈夫曼编码 <span style="white-space:pre"> </span>string code; <span style="white-space:pre"> </span>HuffmanNode<CharInfo>* root = huffTree.GetHuffmanNode(); <span style="white-space:pre"> </span>GenerateHuffmanCode(root, *this, code); <span style="white-space:pre"> </span>//生成压缩文件名及配置配置文件名 <span style="white-space:pre"> </span>string fileNewName = (string)filename; <span style="white-space:pre"> </span>size_t last_ = fileNewName.find_last_of('.'); <span style="white-space:pre"> </span>size_t name_ = fileNewName.find_last_of('\\');//文件名 <span style="white-space:pre"> </span>if (last_ < fileNewName.size()) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>fileNewName.erase(last_); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>char file[10], type[10]; <span style="white-space:pre"> </span>strcpy(file, filename + name_ + 1); //文件名 <span style="white-space:pre"> </span>strcpy(type, filename + last_ ); //文件类型 <span style="white-space:pre"> </span>fileNewName += "_rar\\"; <span style="white-space:pre"> </span>char *fileName = (char *)fileNewName.c_str(), *tag, path[1000]; <span style="white-space:pre"> </span>strcpy(path, fileName); <span style="white-space:pre"> </span>int a = 0; <span style="white-space:pre"> </span>for (tag = fileName; *tag; tag++) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>if (*tag == '\\') <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>a = strlen(fileName) - strlen(tag); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>path[a] = NULL; <span style="white-space:pre"> </span>char filePath[1000]; <span style="white-space:pre"> </span>sprintf(filePath, "md %s", path); <span style="white-space:pre"> </span>system(filePath); <span style="white-space:pre"> </span>fileNewName += file; <span style="white-space:pre"> </span>string fileInName = fileNewName;//压缩文件名 <span style="white-space:pre"> </span>string fileConfig = fileInName;//配置文件名 <span style="white-space:pre"> </span>last_ = fileNewName.find_last_of('.'); <span style="white-space:pre"> </span>if (last_ < fileNewName.size()) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>fileInName.erase(last_); <span style="white-space:pre"> </span>fileConfig.erase(last_); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>fileInName += ".huff"; <span style="white-space:pre"> </span>fileConfig += ".config"; <span style="white-space:pre"> </span>string tmp; <span style="white-space:pre"> </span>//生成压缩配置文件 <span style="white-space:pre"> </span>FILE* fConfig = fopen(fileConfig.c_str(), "wb"); <span style="white-space:pre"> </span>char *tyone = type; <span style="white-space:pre"> </span>for (int i = 0; i < 10; i++) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>fputc(*tyone,fConfig); <span style="white-space:pre"> </span>tyone++; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>char buff[20] = { 0 }; <span style="white-space:pre"> </span>for (size_t i = 0; i < sizeof(this->_info) / sizeof(this->_info[0]); ++i) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>tmp.clear(); <span style="white-space:pre"> </span>if (this->_info[i]._count != 0) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>tmp += this->_info[i]._ch; <span style="white-space:pre"> </span>tmp += ':'; <span style="white-space:pre"> </span>tmp += (string)_itoa((this->_info[i]._count), buff, 10); <span style="white-space:pre"> </span>tmp += '\n'; <span style="white-space:pre"> </span>fputs(tmp.c_str(), fConfig);<span style="white-space:pre"> </span> <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>//对文件进行压缩 <span style="white-space:pre"> </span>FILE* fIn = fopen(fileInName.c_str(), "wb"); <span style="white-space:pre"> </span>assert(fIn); <span style="white-space:pre"> </span>int pos = 0; <span style="white-space:pre"> </span>unsigned char putch = 0; <span style="white-space:pre"> </span>ch = fgetc(fOut); <span style="white-space:pre"> </span>while (!feof(fOut)) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>tmp = this->_info[(unsigned char)ch]._code; <span style="white-space:pre"> </span>for (size_t i = 0; i < tmp.size(); ++i) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>putch <<= 1; <span style="white-space:pre"> </span>putch |= (tmp[i] - '0'); <span style="white-space:pre"> </span>if (++pos == 8) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>fputc(putch, fIn); <span style="white-space:pre"> </span>pos = 0; <span style="white-space:pre"> </span>putch = 0; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>ch = fgetc(fOut); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>if (pos > 0) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>putch <<= (8 - pos); <span style="white-space:pre"> </span>fputc(putch, fIn); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>fclose(fOut); <span style="white-space:pre"> </span>fclose(fIn); <span style="white-space:pre"> </span>fclose(fConfig); } void FileCompress::GenerateHuffmanCode(HuffmanNode<CharInfo>* root, FileCompress& file, string& code) { <span style="white-space:pre"> </span>if (root == NULL) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>return; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>if (root->_left == NULL && root->_right == NULL) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>file._info[root->_weight._ch]._code = code; <span style="white-space:pre"> </span>return; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>code.push_back('0'); <span style="white-space:pre"> </span>GenerateHuffmanCode(root->_left, file, code); <span style="white-space:pre"> </span>code.pop_back(); <span style="white-space:pre"> </span>code.push_back('1'); <span style="white-space:pre"> </span>GenerateHuffmanCode(root->_right, file, code); <span style="white-space:pre"> </span>code.pop_back(); } void FileCompress::UnCompressHuffCode(const char* filename) { <span style="white-space:pre"> </span>assert(filename); <span style="white-space:pre"> </span>FILE* fOut = fopen(filename, "rb"); <span style="white-space:pre"> </span>assert(fOut); <span style="white-space:pre"> </span>//读取文件, <span style="white-space:pre"> </span>string fileConfig = (string)filename; <span style="white-space:pre"> </span>string fileNewName = (string)filename; <span style="white-space:pre"> </span>string fileInName = fileConfig; <span style="white-space:pre"> </span>size_t last_ = fileInName.find_last_of('.'); <span style="white-space:pre"> </span>size_t name_ = fileNewName.find_last_of('\\'); <span style="white-space:pre"> </span>if (name_ < fileNewName.size()) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>fileConfig.erase(last_); <span style="white-space:pre"> </span>fileNewName.erase(name_); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>char file[10]; <span style="white-space:pre"> </span>strcpy(file, fileConfig.c_str() + name_ + 1);//文件名 <span style="white-space:pre"> </span>name_ = fileNewName.find_last_of('\\'); <span style="white-space:pre"> </span>if (name_ < fileInName.size()) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>fileInName.erase(name_+1); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>fileInName += file; //弥补文件名 <span style="white-space:pre"> </span>fileConfig += ".config"; <span style="white-space:pre"> </span>FILE* fConfig = fopen(fileConfig.c_str(), "rb"); <span style="white-space:pre"> </span>assert(fConfig); <span style="white-space:pre"> </span>//修改_count,注意\n,有可能代表字符,有可能是行结束标志 <span style="white-space:pre"> </span>char buff[20] = { 0 }, type[10] = { 0 }; <span style="white-space:pre"> </span>char *tyone = type; <span style="white-space:pre"> </span>for (int i = 0; i < 10; i++) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>*tyone = fgetc(fConfig); <span style="white-space:pre"> </span>tyone++; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>unsigned char ch = fgetc(fConfig); <span style="white-space:pre"> </span>while (!feof(fConfig)) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>fgetc(fConfig);//读取冒号 <span style="white-space:pre"> </span>fgets(buff, 20, fConfig); <span style="white-space:pre"> </span>this->_info[ch]._count = (TypeLong)atoi((buff)); <span style="white-space:pre"> </span>ch = fgetc(fConfig); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>fileInName += "_unrar"; <span style="white-space:pre"> </span>fileInName += type; <span style="white-space:pre"> </span>FILE* fIn = fopen(fileInName.c_str(), "wb"); <span style="white-space:pre"> </span>assert(fIn); <span style="white-space:pre"> </span>//重建哈夫曼树 <span style="white-space:pre"> </span>HuffmanTree<CharInfo> tree(this->_info, sizeof(this->_info) / sizeof(this->_info[0]), 0); <span style="white-space:pre"> </span>HuffmanNode<CharInfo>* root = tree.GetHuffmanNode(); <span style="white-space:pre"> </span>HuffmanNode<CharInfo>* cur = root; <span style="white-space:pre"> </span>TypeLong countSum = root->_weight._count; //记录字符的总个数控制结束 <span style="white-space:pre"> </span>ch = fgetc(fOut); <span style="white-space:pre"> </span>int pos = 7; <span style="white-space:pre"> </span>while (countSum > 0) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>while (pos >= 0) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>if ((ch & (1 << pos)) == 0) //向左走 <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>cur = cur->_left; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>else <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>cur = cur->_right; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>if (cur->_left == NULL && cur->_right == NULL) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>fputc(cur->_weight._ch, fIn); #ifndef __DEBUG_COUT__ <span style="white-space:pre"> </span>cout << cur->_weight._ch; #endif /*__DEBUG_COUT__*/ <span style="white-space:pre"> </span>if (--countSum == 0)//将没有写的字符的次数减1 <span style="white-space:pre"> </span>break; <span style="white-space:pre"> </span>cur = root; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>--pos; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>pos = 7; <span style="white-space:pre"> </span>ch = fgetc(fOut); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>fclose(fIn); <span style="white-space:pre"> </span>fclose(fOut); <span style="white-space:pre"> </span>fclose(fConfig); } void FileCompress::PrintCode()const { <span style="white-space:pre"> </span>for (int i = 0; i < 256; ++i) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>if (this->_info[i]._count != 0) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>cout << this->_info[i]._ch << ":>" << this->_info[i]._code << endl; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>} }
测试代码:压缩测试函数,放在主函数里
void test() { string filename = "C:\\Users\\小明\\Desktop\\input.txt"; cout << "压缩时间"; MyTimer timer; timer.Start(); //////////////////////////////// FileCompress fc; fc.CompressHuffCode(filename.c_str()); ///////////////////////////////// timer.Stop(); timer.showTime(); }
测试代码:解压缩测试函数,放在主函数里
void untest() { string filename = "C:\\Users\\小明\\Desktop\\input_rar\\input.huff"; cout << "解压时间"; MyTimer timer; timer.Start(); //////////////////////////////// FileCompress unfc; unfc.UnCompressHuffCode(filename.c_str()); ///////////////////////////////// timer.Stop(); timer.showTime(); }
主函数:test.cpp
#define _CRT_SECURE_NO_WARNINGS 1 #include <iostream> using namespace std; #include "HuffmanTree.hpp" #include "FileCompress.h" #include "FileCompress.cpp" #include "TimeCheck.h" void test() { string filename = "C:\\Users\\小明\\Desktop\\input.txt"; //需要压缩的文件 cout << "压缩时间"; MyTimer timer; timer.Start(); //////////////////////////////// FileCompress fc; fc.CompressHuffCode(filename.c_str()); ///////////////////////////////// timer.Stop(); timer.showTime(); } void untest() { string filename = "C:\\Users\\小明\\Desktop\\input_rar\\input.huff"; //需要解压缩的文件名 cout << "解压时间"; MyTimer timer; timer.Start(); //////////////////////////////// FileCompress unfc; unfc.UnCompressHuffCode(filename.c_str()); ///////////////////////////////// timer.Stop(); timer.showTime(); } int main() { test(); untest(); system("pause"); return 0; }
现在测试的是我桌面上的一个文件:文件名为:input.txt
压缩过程
压缩和解压缩之后桌面显示:
解压缩文件:input_Com.txt
本项目特点:将压缩后的文件,以及配置文件新建立了一个文件夹,放在文件夹中,这样美观,易识别。
代码中还有很多不足,有些问题也未解决,欢迎各位批评指正!!! 我也会子啊后续努力中继续添加功能!
相关文章推荐
- [置顶] Android 应用内禁止截屏功能的实现
- [置顶] 微信小程序应用—SmallReader微阅读的实现
- [置顶] android应用中去android市场去评分的功能实现(吐槽一波个人应用上线...)
- [置顶] 树:哈夫曼树和哈夫曼编码的详细介绍以及代码实现
- [置顶] 实现网站应用钉钉扫码登录,及查询用户详细信息
- [置顶] ExtJs4.2应用:使用ExtJs扩展组件searchfield实现数据搜索功能
- 优先队列的实现及其在哈夫曼编码中的应用
- [置顶] Android实现应用的增量更新\升级 标签: 增量更新Androidbsdiffpatch增量升级 2016-01-25 16:01
- [置顶] Redis应用3-基于Redis消息队列实现的异步操作
- [置顶] RANSAC算法应用及opencv实现
- [置顶] ExtJs4.2应用:ExtJs4.2+Mysql+Struts2+Hibernate3实现分页查询
- [置顶] Android实现点击两次返回键和长按返回键退出应用实践
- [置顶] Android实现应用的增量更新\升级
- 二叉树应用之哈夫曼编码(二叉链表实现)
- [置顶] etcd:从应用场景到实现原理的全方位解读
- [置顶] 【Android应用开发】-(18)静默方式实现批量安装卸载应用程序
- [置顶] c++实现哈夫曼编码完整代码
- 《哈夫曼编码的实现和应用(编码和译码)》
- [置顶]白话贝叶斯理论及在足球比赛结果预测中的应用和C#实现
- [置顶] spring boot 使用activeMQ实现消息队列简单应用