哈夫曼编码

本文详细介绍了哈夫曼编码的原理,包括如何根据字符出现的概率构建最优二叉树,生成前缀码,以及哈夫曼编码的非唯一性。通过具体的C++代码示例,展示了哈夫曼树的构建过程、编码和解码的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 哈夫曼编码就是根据不同字符出现的概率构建最优二叉树,生成最优前缀码,也就是每个字符的哈夫曼编码(二进制数)。

 哈夫曼编码生成的过程是利用哈夫曼算法创建最优二叉树,在最优二叉树的左子树标0,右子树标为1,从树根遍历到树叶得到的二进制数就是该字符的哈弗曼编码。并且哈夫曼编码不是唯一的,因为当有两个字符概率相等时,树叶所代表的的字符并不是固定的,所以从树根到树叶的路径也不是唯一的,所以哈夫曼编码不是唯一的。

#include "pch.h"
#include <iostream>
#include<string>
using namespace std;

struct HuffmanTree
{
	double weight;                   //权值
	string ch;                   //存放字符
	string code;                     //存放编码
	int parent, lchild, rchild;
};
void Select(HuffmanTree *HT, int *s_1, int *s_2, int end)                        //选择出最小的两个权
{
	double min_1, min_2, min;
	int i = 0;
	while (i < end && (HT + i)->parent != -1)
	{
		i++;
	}
	min_1 = (HT + i)->weight;
	*s_1 = i;
	i++;
	while (i < end && (HT + i)->parent != -1)
	{
		i++;
	}
	min_2 = (HT + i)->weight;
	*s_2 = i;
	i++;
	int *s;
	if (min_1 >= min_2)        //min_1是最小的
	{
		min = min_1;
		min_1 = min_2;
		min_2 = min;
		s = s_1;
		s_1 = s_2;
		s_2 = s;
	}
	while (i < end )
	{
		if ((HT + i)->weight < min_1 && (HT + i)->parent == -1)
		{
			min_2 = min_1;
			*s_2 = *s_1;
			min_1 = (HT + i)->weight;
			*s_1 = i;
		}
		else if ((HT + i)->weight < min_2 && (HT + i)->weight >= min_1 && (HT + i)->parent == -1)
		{
			min_2 = (HT + i)->weight;
			*s_2 = i;

		}
		i++;
	}

}
void SetHuffmanTree(HuffmanTree *HT, int n,char c[])
{
	int weight;
	string  c1;
	int i_1, i_2;
	for (int i = 0; i < n; i++)
	{
		cin >> weight;
	//	cin >> c1;
		(HT + i)->weight = weight;
		(HT + i)->parent = -1;
		(HT + i)->lchild = -1;
		(HT + i)->rchild = -1;
		(HT + i)->code = "";
		(HT + i)->ch = c[i];
	}
	for (int i = n; i < 2 * n - 1; i++)
	{
		(HT + i)->parent = -1;
		Select(HT, &i_1, &i_2, i);
		(HT + i)->weight = (HT + i_1)->weight + (HT + i_2)->weight;
		(HT + i_1)->parent = i;
		(HT + i_2)->parent = i;
		(HT + i)->lchild = i_1;
		(HT + i)->rchild = i_2;
	}
	(HT + 2 * n - 2)->parent = -1;
}
void  Huffman_Code(HuffmanTree *HT, int n)            //编码
{
	int i, j, k;
	string str = "";
	for (i = 0; i < n; i++)
	{
		str = "";
		j = i;
		while (HT[j].parent != -1)
		{
			k = HT[j].parent;
			if (HT[k].lchild == j)
				str += "0";
			else
				str += "1";
			j = k;
		}	
		for (int l = str.size()-1; l >= 0; l--)
		{
			HT[i].code += str[l];                  //保存编码
		}
		cout << HT[i].ch << ":" << HT[i].code << endl;
	}
}
void Huffman_Decode(HuffmanTree *HT, int n,string s)      //解码
{
	string temp = "", str = "";
	for (int i = 0; i < s.size(); i++)
	{
		temp += s[i];
		for (int j = 0; j < n; j++)
		{
			if (temp == HT[j].code)
			{
				str += HT[j].ch;
				temp = "";
				break;
			}
			else if (i == s.size() - 1 && j == n - 1 && temp != "")
			{
				cout << endl;
				cout << "解码错误" << endl;
				exit(0);
			}

		}
	}
	cout << "解码为:" << str << endl;
}
void ShowHuffmanTree(HuffmanTree *HT, int n)        //输出哈夫曼树
{
	cout << (HT + n)->weight << "  ";
	if ((HT + n)->lchild != -1 && (HT + n)->rchild != -1)
	{
		ShowHuffmanTree(HT, (HT + n)->lchild);
		ShowHuffmanTree(HT, (HT + n)->rchild);
	}
}
int main()
{
	cout << "请输入要创建哈夫曼树的权值个数:" << endl;
	int n=5;
	//cin >> n;
	cout << "请输入权值:" << endl;
	char c[5] = { 'A','B','C','D','E' };
	HuffmanTree *HT = new HuffmanTree[2 * n - 1];
	SetHuffmanTree(HT, n,c);
	Huffman_Code(HT, n);
	string str;
	cout << "请输入编码:" << endl;
	cin >> str;
	//for (int i = 0; i < n; i++)
	//	cout << HT[i].ch << ":" << HT[i].code << endl;
	Huffman_Decode(HT, n, str);
	delete []HT;
}

运行环境VS2017

运行结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值