模拟Huffman编码

#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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值