项目名称:文件压缩
开发环境:vs2010
运用到的数据结构:
1、heap堆
2、huffmantree哈夫曼树
3、Huffmancode哈夫曼编码
4、面向对象C++编程语言
思路:
1、利用小堆建立哈弗曼树
2、利用哈弗曼树产生哈夫曼编码
3、利用哈夫曼编码对文件进行压缩,产生压缩文件**.compress文件,以及**.config配置文件方便解码
4、利用配置文件获取到文件中每个字符出现的次数
5、利用配置文件用小堆再次建立哈弗曼树
6、利用配置文件建立的哈弗曼树进行解码生成解压后的文件**.uncompress
建立大小堆博文连接在下面
http://blog.youkuaiyun.com/shangguan_1234/article/details/52791719
堆结构的二叉树存储是
最大堆:每个父节点的都大于孩子节点。
最小堆:每个父节点的都小于孩子节点。
这里举小堆的例子
将每个子孩子与父节点的值进行比较,如果比父节点小则父节点下移,较小的子孩子上移
#pragma once
#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 = Less<T>>
class Heap
{
public:
Heap()
{}
Heap(const T* a, size_t size)
{
for (size_t i = 0; i < size; ++i)
{
_infosays.push_back(a[i]);
}
// 建堆
for (int i = (_infosays.size() - 2) / 2; i >= 0; --i)
{
AdjustDown(i);
}
}
void Push(const T& x)
{
_infosays.push_back(x);
AdjustUp(_infosays.size() - 1);
}
void Pop()
{
assert(_infosays.size() > 0);
swap(_infosays[0], _infosays[_infosays.size() - 1]);
_infosays.pop_back();
AdjustDown(0);
}
const T& Top()
{
//assert(_infosays.size() > 0);
if (!Empty())
{
return _infosays[0];
}
}
bool Empty()
{
return _infosays.empty();
}
int Size()
{
return _infosays.size();
}
void AdjustDown(int root)
{
size_t child = root * 2 + 1;
Compare com;
while (child < _infosays.size())
{
if (child + 1<_infosays.size() &&
com(_infosays[child + 1], _infosays[child]))
{
++child;
}
if (com(_infosays[child], _infosays[root]))
{
swap(_infosays[child], _infosays[root]);
root = child;
child = 2 * root + 1;
}
else
{
break;
}
}
}
void AdjustUp(int child)
{
int parent = (child - 1) / 2;
while (child > 0)
{
if (Compare()(_infosays[child], _infosays[parent]))
{
swap(_infosays[parent], _infosays[child]);
child = parent;
parent = (child - 1) / 2;
}
else
{
break;
}
}
}
void Print()
{
for (size_t i = 0; i < _infosays.size(); ++i)
{
cout << _infosays[i] << " ";
}
cout << endl;
}
public:
vector<T> _infosays;
};
利用堆建立哈夫曼树
Huffm an树,又称为最优二叉树,是加权路径长度最短的二叉树。
【贪心算法】是指在问题求解时,总是做出当前看起来最好的选择。也就是说贪心算法做出的不是整体最优的的选择,而是某种意义上的
局部最优解。贪心算法不是对所有的问题都能得到整体最优解。
使用贪心算法构建Huffman树
#pragma once
#include "Heap.h"
#include<assert.h>
using namespace std;
template<class T>
struct HuffmanTreeNode
{
HuffmanTreeNode<T>* _left;
HuffmanTreeNode<T>* _right;
HuffmanTreeNode<T>* _parent;
T _weight;
HuffmanTreeNode(const T& x)
:_weight(x)
, _left(NULL)
, _right(NULL)
, _parent(NULL)
{}
};
template<class T>
class HuffmanTree
{
typedef HuffmanTreeNode<T> Node;
public:
HuffmanTree()
:_root(NULL)
{}
~HuffmanTree()
{
Destory(_root);
}
template <class T>
struct NodeCompare
{
bool operator()(Node *l, Node *r)
{
return l->_weight < r->_weight;
}
};
void CreatTree(const T* a, size_t size, const T& invalid)
{
assert(a);
Heap<Node*, NodeCompare<T>> minHeap;
for (size_t i = 0; i < size; ++i)
{
if (a[i] != invalid)
{
Node* node = new Node(a[i]);
minHeap.Push(node);
}
}
while (minHeap.Size() > 1)
{
Node* left = minHeap.Top();
minHeap.Pop();
Node* right = minHeap.Top();
minHeap.Pop();
Node* parent = new Node(left->_weight + right->_weight);
parent->_left = left;
parent->_right = right;
left->_parent = parent;
right->_parent = parent;
minHeap.Push(parent);
}
_root = minHeap.Top();
}
Node* GetRootNode()
{
return _root;
}
//void Destory(Node* root)
//{
// if (root)
// {
// Destory(root->_left);
// Destory(root->_right);
// delete root;
// root = NULL;
// }
//}
void Destory(Node* root)
{
if (root==NULL)
{
return ;
}
if(root->_left==NULL&&root->_right==NULL)
{
delete root;
root=NULL;
}
else
{
Destory(root->_left);
Destory(root->_right);
}
}
private:
HuffmanTreeNode<T>* _root;
};
利用哈弗曼树产生哈夫曼编码
代码实现
void _GenerateHuffmanCode(HuffmanTreeNode<CharInfo>* root)//创建哈夫曼编码
{
if (root == NULL