哈夫曼编码

[问题描述]
设某编码系统共有 n 个字符,使用频率分别为{ w1, w2, …, wn},设计一个不等长的 编码方案,使得该编码系统的空间效率最好。
[基本要求]
① 设计数据结构;
② 设计编码算法;
③ 分析时间复杂度和空间复杂度。
[实现提示]
利用哈夫曼编码树求得最佳的编码方案。利用哈夫曼算法建立哈夫曼树,在哈夫曼树中, 设左分支为 0,右分支为 1,从根结点出发,遍历整棵哈夫曼树,求得各叶子结点所表示字 符的哈夫曼编码。
[思维扩展]
对于采用哈夫曼编码树进行的编码,如何设计解码算法?
假设输入了n个字符作为哈夫曼树的叶子结点,那么哈夫曼树中的总结点个数就是2n-1个,根据输入的每个字符对应的权值大小(根据权值大的字符在上面,权值小的字符在下面)建立哈夫曼树。
1)数据结构:

typedef struct
{
	float weight;//哈夫曼树的权值
	int parent, lchild, rchild;//对应的父母节点,左孩子,右孩子节点
} hufmtree;//树节点
typedef struct{
	char bits[n];//编码
	int start;//起始点
	float ch;//对应的权值
}Codetype;// 哈夫曼树编码
hufmtree tree[2 * n - 1];
Codetype code[n];

2)算法
1.创建哈夫曼树

void C_H(){
int i, j, p1, p2;
		float small1, small2, f;
		for (i = 0; i < m; i++)
		{ //初始化数组
			tree[i].parent = 0;
			tree[i].lchild = 0;
			tree[i].rchild = 0;
			tree[i].weight = 0.0;
		}
		for (i = 0; i < n; i++)
		{ //读入前n个节点的权值
			scanf("%f",&f);
			tree[i].weight = f;
		}
		for (i = n; i < m; i++)
		{ // n-1次合并.产生n-1个新节点
			p1 = p2 = 0;
			small1 = small2 = max;
			for (j = 0; j <= i - 1; j++) //选两权值最小根节点
			{
				if (tree[j].parent != 0){// j节点加入树中
					continue;
				}
				else{
					if (tree[j].weight < small1)
					{ //查找最小权.用p1记录下标
						small2 = small1;
						small1 = tree[j].weight;
						p2 = p1;
						p1 = j;
					}
					else if (tree[j].weight < small2)
					{ //查找次小权.用p2记录其下标
						small2 = tree[j].weight;
						p2 = j;
					}
				}
			}
			tree[p1].parent = i;
			tree[p2].parent = i;
			tree[i].weight = tree[p1].weight + tree[p2].weight;
			tree[i].lchild = p1;
			tree[i].rchild = p2;
		}
}

2.形成编码:

void H_c(){
		int i,j,p;
		for ( i = 0; i < n; i++)
		{
			code[i].start=n-1;
			code[i].ch=tree[i].weight;
			j=i;
			p=tree[i].parent;
			while(p!=0){
				if(tree[p].lchild==j) code[i].bits[code[i].start]='0';
				else code[i].bits[code[i].start]='1';
				code[i].start--;
				j=p;
				p=tree[p].parent;
			}
		}
}

3).主函数

int main(){
	C_H();
	int i,j;
	H_c();
	for ( i = 0; i < n; i++)
	{
		printf("%.1f ",code[i].ch);
		for ( j = 0; j <n ; j++)
		{
			printf("%c",code[i].bits[j]);
		}
		printf(" ");
	}
	return 0;
}

4).运行结果
在这里插入图片描述
说明:第一行为输入的五个权值
第二行为每个权值对应的编码
思考:
哈夫曼树每个结点可能存在左右孩子结点,左孩子的编码为0,右孩子的编码为1,通过从根节点遍历哈夫曼树,对每个叶子节点中对应的字符进行编码。解码时通过判断二进制数中的0或1查找叶子节点中的字符。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值