#include<iostream>
#include<vector>
#include<assert.h>
using namespace std;
template<class T>
struct Less
{
bool operator()(const T& l, const T& r)
{
return l < r;
}
};
template<class T>
struct Greater
{
bool operator()(const T& l, const T& r)
{
return l>r;
}
};
template<class T,class compare=Greater<T>>
class Heap
{
public:
Heap()
{}
Heap(const T *arr, size_t size)
{
assert(arr);
for (size_t i = 0; i < size; ++i)
_arr.push_back(arr[i]);
int begin = (_arr.size()-2)/2;
for (; begin >= 0; --begin)
_AdjustDown(begin);
}
void Push(const T& x)
{
_arr.push_back(x);
int begin = _arr.size() - 1;
_AdjustUp(begin);
}
void Pop()
{
if (_arr.size() <= 0)
return;
swap(_arr[0], _arr[_arr.size() - 1]);
_arr.pop_back();
_AdjustDown(0);
}
T& Top()
{
if (!IsEmpty())
return _arr[0];
exit(1);
}
bool IsEmpty()
{
return _arr.empty();
}
size_t Size()
{
return _arr.size();
}
void Print()
{
for (size_t i = 0; i < _arr.size(); ++i)
cout << _arr[i] << " ";
cout << endl;
}
protected:
void _AdjustDown(int parent)
{
compare com;
int child = 2 * parent+1;
while (child < _arr.size())
{
if (child + 1 < _arr.size() && com(_arr[child+1], _arr[child]))
child++;
if (com(_arr[child], _arr[parent]))
{
swap(_arr[parent], _arr[child]);
parent = child;
child = parent * 2 + 1;
}
else
break;
}
}
void _AdjustUp(int child)
{
compare com;
int parent = (child - 1) / 2;
while (parent >= 0)
{
if (com(_arr[child], _arr[parent]))
{
swap(_arr[parent], _arr[child]);
child = parent;
parent = (child - 1) / 2;
}
else
break;
}
}
private:
vector<T> _arr;
};
void TestHeap()
{
int a[] = { 1, 2, 4, 3,5,0,7 };
Heap<int> h;
for (int i = 0; i < sizeof(a) / sizeof(a[0]); ++i)
h.Push(a[i]);
h.Print();
h.Pop();
h.Print();
h.Pop();
h.Print();
}
#pragma once
#include<iostream>
#include<vector>
#include<assert.h>
#include"Heap.h"
using namespace std;
template<class T>
struct HuffmanNode
{
T _weight;
HuffmanNode<T>* _parent;
HuffmanNode<T>* _left;
HuffmanNode<T>* _right;
HuffmanNode(const T& weight)
:_weight(weight)
, _parent(NULL)
, _left(NULL)
, _right(NULL)
{}
};
template<class T>
class HuffmanTree
{
typedef HuffmanNode<T> Node;
public:
HuffmanTree()
:_root(NULL)
{}
HuffmanTree(T *arr, size_t size, const T& invalid)
{
assert(arr);
_CreateHuffman(arr, size, invalid);
}
~HuffmanTree()
{
_DestoryTree(_root);
}
template<class T>
struct CompareLess
{
bool operator()(Node* l, Node* r)
{
return l->_weight < r->_weight;
}
};
Node* GetRootNode()
{
return _root;
}
void PrintTree()
{
_Print(_root);
cout << endl;
}
protected:
void _CreateHuffman(const T *arr, size_t size, const T& invalid)
{
Node* parent;
Node* left;
Node* right;
Heap<Node*, CompareLess<T>> h;
for (size_t i = 0; i < size; ++i)
{
if (arr[i] != invalid)
{
Node* tmp = new Node(arr[i]);
h.Push(tmp);
}
}
while (h.Size()>1)
{
left = h.Top();
h.Pop();
right = h.Top();
h.Pop();
parent = new Node(left->_weight + right->_weight);
parent->_left = left;
left->_parent = parent;
parent->_right = right;
right->_parent = parent;
h.Push(parent);
}
_root = h.Top();
}
void _DestoryTree(Node*& root)
{
if (root)
{
_DestoryTree(root->_left);
_DestoryTree(root->_right);
delete root;
}
}
void _Print(Node* root)
{
if (root)
{
cout << root->_weight << " ";
_Print(root->_left);
_Print(root->_right);
}
}
private:
Node* _root;
};
void TestHuffman()
{
int arr[] = { 1,2,4,5,3};
HuffmanTree<int> hf(arr, 5, '#');
hf.PrintTree();
}
#include"HuffmanTree.h"
#include<algorithm>
#include<windows.h>
#include<assert.h>
typedef long long LongType;
struct FileInfo
{
unsigned char _ch;
LongType _count;
string _code;
FileInfo(unsigned char ch= 0)
:_ch(ch)
, _count(0)
{}
FileInfo operator+(FileInfo& fi)
{
FileInfo tmp;
tmp._count = _count + fi._count;
return tmp;
}
bool operator<(FileInfo& fi)
{
return _count < fi._count;
}
bool operator != (const FileInfo& fi) const
{
return _count != fi._count;
}
};
template<class T>
class FileCompress
{
public:
FileCompress()
{
for (int i = 0; i < 256; ++i)
_infos[i] = i;
}
public:
bool Compress(const char* filename)
{
//读取文件中字符出现的次数
long long charCount = 0;
assert(filename);
FILE* fOut = fopen(filename, "rb");
assert(fOut);
char ch = fgetc(fOut);
while (ch != EOF)
{
_infos[(unsigned char)ch]._count++;
ch = fgetc(fOut);
charCount++;
}
//构建HuffmanTree
GenerateHuffmanCode();
//压缩文件
string compressFile = filename;
compressFile += ".compress";
FILE* fwCompress = fopen(compressFile.c_str(), "wb");
fseek(fOut, 0, SEEK_SET);
ch = fgetc(fOut);
char inch = 0;
int index = 0;
while (ch != EOF)
{
string& code = _infos[(unsigned char)ch]._code;
for (size_t i = 0; i < code.size(); ++i)
{
inch = inch << 1;
if (code[i] == '1')
inch |= 1;
if (++index == 8)
{
fputc(inch, fwCompress);
inch = 0;
index = 0;
}
}
ch = fgetc(fOut);
}
if (index)
{
inch = inch << (8 - index);
fputc(inch, fwCompress);
}
//配置文件
string configFile = filename;
configFile += ".config";
FILE *fconfig = fopen(configFile.c_str(), "wb");
assert(fconfig);
char CountStr[128];
_itoa(charCount/* >> 32*/, CountStr, 10);
fputs(CountStr, fconfig);
fputc('\n', fconfig);
//itoa(charCount & 0xffffffff, CountStr, 10);
//fputs(CountStr, fconfig);
//fputc('\n', fconfig);
FileInfo invalid;
for (int i = 0; i < 256; ++i)
{
if (_infos[i] != invalid)
{
_itoa(_infos[i]._count,CountStr, 10);
fputc(_infos[i]._ch, fconfig);
fputc(',', fconfig);
fputc(_infos[i]._count + '0', fconfig);
fputc('\n', fconfig);
}
}
fclose(fOut);
fclose(fwCompress);
fclose(fconfig);
return true;
}
bool UnCompress(const char* filename)
{
string configfile = filename;
configfile += ".config";
FILE* outConfig = fopen(configfile.c_str(), "rb");
assert(outConfig);
char ch;
long long Charcount = 0;
string line;
ReadLine(outConfig,line);
Charcount = atoi(line.c_str());
line.clear();
while (ReadLine(outConfig,line))
{
if (!line.empty())
{
ch = line[0];
_infos[(unsigned char)ch]._count = atoi(line.substr(2).c_str());
line.clear();
}
else
{
line += '\n';
}
}
FileInfo invalid;
HuffmanTree<FileInfo> ht(_infos, 256, invalid);
HuffmanNode<FileInfo>* root = ht.GetRootNode();
string UnCompressFile = filename;
UnCompressFile += ".uncompress";
FILE* fOut = fopen(UnCompressFile.c_str(), "wb");
string CompressFile = filename;
CompressFile += ".compress";
FILE* fIn = fopen(CompressFile.c_str(), "rb");
int pos = 8;
HuffmanNode<FileInfo>* cur = root;
ch = fgetc(fIn);
while ((unsigned char)ch != EOF)
{
if (cur->_left == NULL && cur->_right == NULL)
{
fputc(cur->_weight._ch, fOut);
cur = root;
if (--Charcount == 0)
break;
}
--pos;
if ((unsigned char)ch &(1 << pos))
cur = cur->_right;
else
cur = cur->_left;
if (pos == 0)
{
ch = fgetc(fIn);
pos = 8;
}
}
fclose(outConfig);
fclose(fIn);
fclose(fOut);
return true;
}
protected:
bool ReadLine(FILE* file, string &line)
{
char ch = fgetc(file);
if (ch == EOF)
return false;
while (ch != EOF&&ch != '\n')
{
line += ch;
ch = fgetc(file);
}
return true;
}
void GenerateHuffmanCode()
{
FileInfo invalid;
HuffmanTree<FileInfo> hft(_infos, 256, invalid);
_GenerateHuffmanCode(hft.GetRootNode());
}
void _GenerateHuffmanCode(HuffmanNode<FileInfo>* root)
{
if (root == NULL)
return;
_GenerateHuffmanCode(root->_left);
_GenerateHuffmanCode(root->_right);
if (root->_left == NULL && root->_right == NULL)
{
HuffmanNode<FileInfo>* cur = root;
HuffmanNode<FileInfo>* parent = cur->_parent;
string& code = _infos[cur->_weight._ch]._code;
while (parent)
{
if (parent->_left == cur)
code += '0';
else if (parent->_right == cur)
code += '1';
cur = parent;
parent = cur->_parent;
}
reverse(code.begin(), code.end());
}
}
private:
FileInfo _infos[256];
};
#pragma once
#include"FileCompress.h"
using namespace std;
void TestCompress()
{
FileCompress<FileInfo> fc;
int begin = GetTickCount();
fc.Compress("Input.BIG");
int end = GetTickCount();
cout << "Time Of Compress:" << end - begin << endl;
}
void TestUnCompress()
{
FileCompress<FileInfo> fc;
int Unbegin = GetTickCount();
fc.UnCompress("Input.BIG");
int Unend = GetTickCount();
cout << "Time Of UnCompress:" << Unend - Unbegin << endl;
}
int main()
{
//TestHeap();
TestHuffman();
//TestCompress();
//TestUnCompress();
return 0;
}
文件压缩
最新推荐文章于 2022-04-16 23:58:46 发布