c语言对字符串进行前缀重叠判断_数据结构(C语言)-哈夫曼(Huffman)树编码和译码操作...

导语

本文使用C语言。对某一输入的字符串,对其构造哈夫曼(Huffman)树,并由此树的到字符串中每一个字符的哈夫曼编码

本文哈夫曼树和哈夫曼编码采用顺序存储结构实现

哈夫曼树

给定N个权值作为N个叶子结点,构造一棵二叉树,若该树的带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree)。哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近。

193d0cbfdf382557dfa0cbb5e427e4ba.gif
哈夫曼树,图片来源百度百科

哈夫曼编码

在数据通信中,需要将传送的文字转换成二进制的字符串,用0,1码的不同排列来表示字符。例如,需传送的报文为“AFTER DATA EAR ARE ART AREA”,这里用到的字符集为“A,E,R,T,F,D”,各字母出现的次数为{8,4,5,3,1,1}。

现要求为这些字母设计编码。要区别6个字母,最简单的二进制编码方式是等长编码,固定采用3位二进制,可分别用000、001、010、011、100、101对“A,E,R,T,F,D”进行编码发送,当对方接收报文时再按照三位一分进行译码。显然编码的长度取决报文中不同字符的个数。若报文中可能出现26个不同字符,则固定编码长度为5

然而,传送报文时总是希望总长度尽可能短。在实际应用中,各个字符的出现频度或使用次数是不相同的,如A、B、C的使用频率远远高于X、Y、Z,自然会想到设计编码时,让使用频率高的用短码,使用频率低的用长码,以优化整个报文编码

为使不等长编码为前缀编码(即要求一个字符的编码不能是另一个字符编码的前缀),可用字符集中的每个字符作为叶子结点生成一棵编码二叉树,为了获得传送报文的最短长度,可将每个字符的出现频率作为字符结点的权值赋予该结点上,显然字使用频率越小权值越小,权值越小叶子就越靠下,于是频率小编码长,频率高编码短,这样就保证了此树的最小带权路径长度效果上就是传送报文的最短长度

因此,求传送报文的最短长度问题转化为求由字符集中的所有字符作为叶子结点,由字符出现频率作为其权值所产生的哈夫曼树的问题。利用哈夫曼树来设计二进制的前缀编码,既满足前缀编码的条件,又保证报文编码总长最短,该前缀编码称为哈夫曼编码

2dd7f059d6fa21ae37c8bbb19cb4330e.gif
哈夫曼编码

如上图所示,对于一个字符串“AAABBCCCDDDDE” 来说,很容易知道每个字符出现的频次{3,2,3,4,1}。根据频次,每次选出频次最小的两个结点进行组合,频次相加得到父结点。不断重复此过程,直到产生一颗哈夫曼树。

通过该哈夫曼树,我们可以得到每个字符的哈夫曼编码 A=10,B=001,C=01,D=11,E=000

容易证明,每个字符的编码都是前缀编码

C语言实现哈夫曼编码

网上许多大佬实现哈夫曼树的结点都是采用链式存储结构,而实现哈夫曼编码则是采用指针。

那鄙人就使用顺序存储结构来实现哈夫曼树结点,给大家提供一些思路吧

哈夫曼结点,放在一个数组中,即 HNodeType HuffNodes[]

typedef 

哈夫曼编码结构,也采用顺序存储结构(数组)

typedef 

接受字符串

void 

统计字符频次

int 

找到权值最小的两个结点

// 从 HuffNodes[0..range]中,找到最小的结点索引赋给s1,s2 。已经找到过的结点索引被储存在out[]中 

构造哈夫曼树

//构造一棵Huffman树,树结点存放在HuffNodes中

生成哈夫曼编码

void 

遍历哈夫曼树,使用队列递归方式

int 

主函数

#include 

输出结果

63f5ea8c211827de997fb88ed45646ee.png

以上代码,经过本人调试,没有看出问题来。若有问题,欢迎指正

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值