#pragma once
#ifndef HUFFMAN_H_
#define HUFFMAN_H_
#include<string>
#include<queue>
#include<set>
#include<map>
#include<vector>
#include<algorithm>
#include<iostream>
using namespace std;
template<typename Type>
struct array_data
{
Type Element;
int times;
bool tag;
};
template<typename Type>
struct TreeNode
{
Type Element;
bool tag;
TreeNode<Type>* Left;
TreeNode<Type>* Right;
};
template<typename Type>
struct cmp
{
bool operator()(const array_data<Type>& a, const array_data<Type>& b)const
{
if (a.times > b.times)
return true;
else if (a.times == b.times)
{
if (a.Element > b.Element)//这里注意不能写成>=,要严格写成>
return true;
else
return false;
}
else
return false;
}
};
template<typename Type>
class Huffman
{
private:
TreeNode<Type>* root;//根结点
protected:
TreeNode<Type>* _create_node(const array_data<Type>& old);//创建结点
map<Type, string>Huffman_coding;//存储哈夫曼编码
void coding(const TreeNode<Type>* ptr,const string r="0");//编码
void optimize();//优化编码
void _delete(TreeNode<Type>* ptr);//删除所有树结点
public:
Huffman(const Type* import_Data,int _size);
void show();//输出编码
~Huffman();
};
#endif // !HUFFMAN_H_
template<typename Type>
inline Huffman<Type>::Huffman(const Type* import_Data,int _size)
:root(nullptr)
{
set<Type> _simple_element;//统计不重复的元素
priority_queue<array_data<Type>, vector<array_data<Type>>, cmp<Type>> Queue;//优先队列
for (int i = 0; i < _size; i++)
_simple_element.insert(import_Data[i]);
int n = (int)_simple_element.size();
array_data<Type>* Rec = new array_data<Type>[n];
auto t = _simple_element.begin();
for (int i = 0; i < n; i++)
{
Rec[i].Element = *t;
Rec[i].times = count(import_Data, import_Data + _size, *t);
Rec[i].tag = false;
Queue.push(Rec[i]);//入队
++t;
}
delete[]Rec;
vector<array_data<Type>> _insert_array;//待插入数组
while (Queue.size())
{
if (Queue.size() == 1)//队列中只有一个元素
{
_insert_array.insert(_insert_array.begin(), Queue.top());//直接插入
Queue.pop();
}
else
{
//取队列中前两个插入,并且前两个之和作为新的元素入队
array_data<Type> temp;
_insert_array.insert(_insert_array.begin(), Queue.top());
temp.Element = 0;//这里需不需要无所谓
temp.times = Queue.top().times;
Queue.pop();
_insert_array.insert(_insert_array.begin(), Queue.top());
temp.times += Queue.top().times;
temp.tag = true;
Queue.pop();
Queue.push(temp);
}
}
//for (auto s = _insert_array.begin(); s != _insert_array.end(); s++)
// cout << s->times << endl;
int _limit = (int)_insert_array.size();
queue<TreeNode<Type>*> queue_of_treenode;
root = _create_node(_insert_array[0]);
queue_of_treenode.push(root);
TreeNode<Type>* ptr;
int i = 1;
while (queue_of_treenode.size())
{
ptr = queue_of_treenode.front();//取出队首指针
if (ptr->tag == true)
{
if (i < _limit)
{
ptr->Left =_create_node(_insert_array[i]);
queue_of_treenode.push(ptr->Left);
++i;
if (i < _limit)
{
ptr->Right = _create_node(_insert_array[i]);
queue_of_treenode.push(ptr->Right);
++i;
}
}
}
queue_of_treenode.pop();
}
coding(root);//编码
optimize();//优化
}
template<typename Type>
inline TreeNode<Type>* Huffman<Type>::_create_node(const array_data<Type>& old)
{
TreeNode<Type>* newnode = new TreeNode<Type>;
newnode->Element = old.Element;
newnode->tag = old.tag;
newnode->Left = nullptr;
newnode->Right = nullptr;
return newnode;
}
template<typename Type>
inline void Huffman<Type>::coding(const TreeNode<Type>* ptr,const string r)
{
if (ptr->tag == false)//遇到叶子结点,记录编码
{
Huffman_coding.insert(pair<Type, string>(ptr->Element, r));
return;
}
coding(ptr->Left, r + '0');
coding(ptr->Right, r + '1');
}
template<typename Type>
inline void Huffman<Type>::optimize()
{
for (auto t = Huffman_coding.begin(); t != Huffman_coding.end(); t++)
{
if (t->second[0] == '0')//发现有前缀0,需要消除前缀零
{
int finish = t->second.find_first_of('1');
if (finish == -1)//没有找到'1',即该编码为0
t->second = "0";
else
t->second.erase(t->second.begin(), t->second.begin() + finish);
}
}
}
template<typename Type>
inline void Huffman<Type>::show()
{
for (auto t = Huffman_coding.begin(); t != Huffman_coding.end(); t++)
cout << t->first << ": " << t->second << endl;
}
template<typename Type>
inline void Huffman<Type>::_delete(TreeNode<Type>* ptr)
{
if (ptr == nullptr)
return;
_delete(ptr->Left);
_delete(ptr->Right);
delete ptr;
}
template<typename Type>
inline Huffman<Type>::~Huffman()
{
_delete(root);
}
这是测试数据
#include"Huffman.h"
const int p[28] = { 1,2,2,3,3,3,4,4,4,4,5,5,5,5,5,6,6,6,6,6,6,7,7,7,7,7,7,7 };
int main()
{
Huffman<int> t(p, 28);
t.show();
return 0;
}