图解霍夫曼树-压缩算法的基础

图解霍夫曼树-压缩算法的基础_第1张图片

对于文本”BADCADFEED”的传输而言,因为重复出现的只有

”ABCDEF”这6个字符,因此可以用下面的方式编码:

图解霍夫曼树-压缩算法的基础_第2张图片  

 

接收方可以根据每3个bit进行一次字符解码的方式还原文本信息。

这样的编码方式需要30个bit位才能表示10个字符

 

那么当传输一篇500个字符的情报时,需要15000个bit位

在战争年代,这种编码方式对于情报的发送和接受是很低效且容易出错的。

如何提高收发效率?

 要提高效率,必然要从编码方式的改进入手,要避免每个字符都占用相同的bit位

图解霍夫曼树-压缩算法的基础_第3张图片  

 

准则:任一字符的编码都不是另一个字符编码的前缀!

霍夫曼树
1.给定n个数值{ v1, v2, …, vn}
2.根据这n个数值构造二叉树集合F
F = { T1, T2, …, Tn}
Ti的数据域为vi,左右子树为空
3.在F中选取两棵根结点的值最小的树作为左右子树构造一棵新的二叉树,这棵二叉树的根结点中的值为左右子树根结点中的值之和
4.在F中删除这两棵子树,并将构造的新二叉树加入F中
5.重复3和4,直到F中只剩下一个树为止。这棵树即霍夫曼树

 

 图解霍夫曼树-压缩算法的基础_第4张图片

霍夫曼树是一种特殊的二叉树

霍夫曼树应用于信息编码和数据压缩领域

霍夫曼树是现代压缩算法的基础

 

 图解霍夫曼树-压缩算法的基础_第5张图片

 

#include 
#include 
using namespace std;

//https://blog.csdn.net/dongfei2033/article/details/80657360

typedef struct {
	int weight;         // 结点权值
	int parent, lc, rc; // 双亲结点和左 右子节点
} HTNode, *HuffmanTree;

void Select(HuffmanTree &HT, int n, int &s1, int &s2)
{
	int minum;      // 定义一个临时变量保存最小值
	for (int i = 1; i <= n; i++)     // 以下是找到第一个最小值
	{
		if (HT[i].parent == 0)
		{
			minum = i;
			break;
		}
	}

	for (int i = 1; i <= n; i++)
	{
		if (HT[i].parent == 0)
			if (HT[i].weight < HT[minum].weight)
				minum = i;
	}
	s1 = minum;

	// 以下是找到第二个最小值,且与第一个不同
	for (int i = 1; i <= n; i++)
	{
		if (HT[i].parent == 0 && i != s1)
		{
			minum = i;
			break;
		}
	}
	for (int i = 1; i <= n; i++)
	{
		if (HT[i].parent == 0 && i != s1)
			if (HT[i].weight < HT[minum].weight)
				minum = i;
	}
	s2 = minum;
}

void CreatHuff(HuffmanTree &HT, int *w, int n)
{
	int m, s1, s2;
	m = n * 2 - 1;					// 总结点的个数
	HT = new HTNode[m + 1];			// 分配空间

	//根据n个数值构造二叉树集合
	for (int i = 1; i <= n; i++)		// 1 - n 存放叶子结点,初始化
	{
		HT[i].weight = w[i];
		HT[i].parent = 0;
		HT[i].lc = 0;
		HT[i].rc = 0;
	}

	for (int i = n + 1; i <= m; i++)   // 非叶子结点的初始化
	{
		HT[i].weight = 0;
		HT[i].parent = 0;
		HT[i].lc = 0;
		HT[i].rc = 0;
	}

	printf("\nthe HuffmanTree is: \n");

	for (int i = n + 1; i <= m; i++)     // 创建非叶子节点,建哈夫曼树
	{   
		// 在HT[1]~HT[i-1]的范围内选择两个parent为0且weight最小的两个结点,其序号分别赋值给 s1 s2
		Select(HT, i - 1, s1, s2);

		HT[s1].parent = i;  // 删除这两个结点 
		HT[s2].parent = i;
		HT[i].lc = s1;      // 生成新的树,左右子节点是 s1和s2
		HT[i].rc = s2;
		HT[i].weight = HT[s1].weight + HT[s2].weight;   // 新树的权值
		printf("%d (%d, %d)\n", HT[i].weight, HT[s1].weight, HT[s2].weight);
	}
	printf("\n");
}

int main()
{
	HuffmanTree HT;

	int *w, n, wei;
	printf("input the number of node\n");
	scanf("%d", &n);
	w = new int[n + 1];
	printf("\ninput the %dth node of value\n", n);

	for (int i = 1; i <= n; i++)
	{
		scanf("%d", &wei);
		w[i] = wei;
	}
	CreatHuff(HT, w, n);
	return 0;
}

 图解霍夫曼树-压缩算法的基础_第6张图片

你可能感兴趣的:(数据结构)