哈弗曼编码

哈弗曼编码


问题描述:给定字符集C和每个字符的频率,求关于C的一个最优前缀码。

算法分析:构造最优前缀码的贪心算法就是哈夫曼算法(Huffman)

二元前缀编码存储:二叉树结构,每个字符作为树叶,对应这个字符的前缀码看作根到这片树叶的一条路径,每个结点通向左二子的边记作0,通向右儿子的边记作1.

#include <iostream>
#include <string>
#include <vector>
#include<algorithm>
using namespace std;
class Huffman
{
public:
	char elementChar;//节点元素
	int weight;//权重
	char s;//哈夫曼编码
	Huffman* parent;//父节点
	Huffman* leftChild;//左孩子
	Huffman* rightChild;//右孩子
public:
	Huffman();
	Huffman(char a, int weight);
	bool operator < (const Huffman &m)const { return weight < m.weight;}
};
Huffman::Huffman()
{
	this->s = ' ';
	this->elementChar = '*';//非叶子节点
	this->parent = this->leftChild = this->rightChild = NULL;
}
Huffman::Huffman(char a, int weight):elementChar(a),weight(weight)
{
	this->s = ' ';
	this->elementChar = '*';//非叶子节点
	this->parent = this->leftChild = this->rightChild = NULL;
}

//递归输出哈夫曼值
void huffmanCode(Huffman & h)
{
	if(h.leftChild == NULL && h.rightChild == NULL)
	{
		//如果是叶子节点,输出器哈夫曼编码
		string s;
		Huffman temp = h;
		while(temp.parent != NULL)
		{
			s = temp.s + s;
			temp = *temp.parent;
		}
		cout << h.elementChar << "的哈夫曼编码是:" << s << endl;
		return;
	}
	//左孩子
	huffmanCode(*h.leftChild);
	//右孩子 
	huffmanCode(*h.rightChild);
}
int main()
{
	string huffmanStr;
	cout << "请输入一串字符序列:" << endl;
	cin >> huffmanStr;
	//得到字符串信息
	int i=0,j,n,m[100],h,k=0;
	char cha[100];
	n = huffmanStr.length();
	cout << "字符串总共有字符" << n << "个" << endl;
	for(int i = 0; i < n; i++)
	{
		j = 0; h = 0;
		while(huffmanStr[i] != huffmanStr[j])
			j++;
		if(j == i)
		{
			cha[k] = huffmanStr[i];
			cout << "字符" << cha[k] << "出现";
		}
		//如果j !=i 则略过此次循环
		else
			continue;

		for(j = i; j < n; j++)
		{
			if(huffmanStr[i] == huffmanStr[j])
				h++;
		}
		cout << h << "次" << endl;
		m[k] = h;
		k++;
	}
	//哈夫曼编码
	Huffman huffmanTemp;
	vector < Huffman > huffmanQueue;
	//初始化队列
	for(int i = 0; i < k; i++)
	{
		huffmanTemp.elementChar = cha[i];
		huffmanTemp.weight = m[i];
		huffmanQueue.push_back(huffmanTemp);
	} 
	//得到哈夫曼树所有节点
	int huffmanQueue_index = 0;
	sort(huffmanQueue.begin(), huffmanQueue.end());
	while(huffmanQueue.size() < 2 * k - 1)
	{
		//合成最小两个节点的父节点
		huffmanTemp.weight = huffmanQueue[huffmanQueue_index].weight + huffmanQueue[huffmanQueue_index + 1].weight;
		huffmanQueue[huffmanQueue_index].s = '0';
		huffmanQueue[huffmanQueue_index + 1].s = '1';
		huffmanTemp.elementChar = '*';
		//将父节点加入队列
		huffmanQueue.push_back(huffmanTemp);
		sort(huffmanQueue.begin(), huffmanQueue.end());
		huffmanQueue_index += 2;
	}
	//把所有节点构造成哈夫曼树
	int step = 0;//步长
	while(step + 2 < 2 * k)
	{
		for(int j = step + 1; j <= huffmanQueue.size(); j++)
		{
			if(huffmanQueue[j].elementChar == '*' && huffmanQueue[j].leftChild == NULL && (huffmanQueue[j].weight == huffmanQueue[step].weight + huffmanQueue[step+1].weight))
			{
				huffmanQueue[j].leftChild = &huffmanQueue[step];
				huffmanQueue[j].rightChild = &huffmanQueue[step+1];
				huffmanQueue[step].parent = huffmanQueue[step+1].parent = &huffmanQueue[j];
				break;
			}
		}
		step += 2;
	}
	//cout << huffmanQueue.size() << endl;
	//序列最后一个元素,即哈弗曼树最顶端的节点
	huffmanTemp = huffmanQueue.back();
	huffmanCode(huffmanTemp);
	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值