哈夫曼编码

哈夫曼编码的第一步是构造哈夫曼树, 第二步是为哈夫曼树的每一条边编码。

构造哈夫曼树的时候,每次取权值最小的两个边合并,边小的放左边,边大的放右边。

哈夫曼树的结点总个数是哈夫曼叶节点个数的2倍减1

代码实现:

#include <iostream>
#include <string>

using namespace std;

struct Node
{
	int lChild, rChild, parent;
	string code;
	int weight;
	string c;
};

//从当前叶节点和已经构造的节点中选出最小的两个数
void Select(Node nd[], int n, int& a, int &b)
{
	//find the minimum
	double wt = 0;
	for (int i = 0; i < n; ++i)
	{
		if (nd[i].parent != -1)
			continue;
		if (wt == 0 && nd[i].parent == -1)
		{
			wt = nd[i].weight;
			a = i;
		}
		else if (nd[i].parent == -1 && nd[i].weight < wt)
		{
			wt = nd[i].weight;
			a = i;
		}
	}
	
	//寻找第二小的数
	wt = 0;
	for (int i = 0; i < n; ++i)
	{
		if (nd[i].parent != -1 || i == a)
			continue;
		if (wt == 0 && nd[i].parent == -1)
		{
			wt = nd[i].weight;
			b = i;
		}
		else if (nd[i].parent == -1 && nd[i].weight < wt)
		{
			wt = nd[i].weight;
			b = i;
		}
	}
}

//构造huffman树
void HuffTree(int w[], string ch[], int N, int M, Node nd[])
{
	//初始化Node数组
	for (int i = 0; i < M; ++i)
	{
		//-1代表没有
		nd[i].lChild = -1;
		nd[i].rChild = -1;
		nd[i].parent = -1;
		nd[i].code = "";
	}
	for (int i = 0; i < N; ++i)
	{
		nd[i].weight = w[i];
		nd[i].c = ch[i];
	}

	for (int i = N; i < M; ++i)
	{
		int a = 0, b = 0;
		Select(nd, i, a, b);
		nd[a].parent = i;
		nd[b].parent = i;
		nd[i].lChild = a;
		nd[i].rChild = b;
		nd[i].weight = nd[a].weight + nd[b].weight;
	}
}

void HuffEnCode(Node nd[], int N)
{
	int i, j, k;
	for (int i = 0; i < N; ++i)
	{
		string s = "";
		j = i;
		//从叶节点一直找到根节点
		while (nd[j].parent != -1)
		{
			k = nd[j].parent;
			if (nd[k].lChild == j)
			{
				s = s + "0";
			}
			else
			{
				s = s + "1";
			}
			j = k;
		}
		for (int x = s.size(); x >= 0; --x)
			nd[i].code += s[x];
		cout << nd[i].c << "编码为:  " << nd[i].code << endl;
	}
}

void HuffmanDecode(Node nd[], string str, int N, int M)
{
	string res = "";
	int i = 0, j = 0;
	int p = M - 1;
	while (i < str.size())
	{
		if (str[i] == '0')
			p = nd[p].lChild;
		if (str[i] == '1')
			p = nd[p].rChild;
		//找到了叶节点
		j = p;
		if (p < N)
		{
			res += nd[p].c;
			//重新回到叶节点
			p = M - 1;
		}
		++i;
	}
	if (j >= N)
		cout << "解码错误";
	else
		cout << res << endl;
}

int main()
{
	int wt[5] = { 5, 10, 20, 40, 25 };
	string ch[] = { "A", "B", "C", "D", "E" };
	Node nd[9]; //n个叶节点构造的哈夫曼树的结点个数为2n - 1
	HuffTree(wt, ch, 5, 9, nd);
	HuffEnCode(nd, 5);
	string str;
	cin >> str;
	HuffmanDecode(nd, str, 5, 9);
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值