哈夫曼编码,香农编码,费诺编码的比较

一、费诺编码属于统计匹配编码,其编码步骤为::(1)将信源消息(符号)按其出现的概率由大到小依次排列;(2)将依次排列的信源符号按概率值分为两大组,使两个组的概率之和近于相同,并对各组分别赋予一个二进制码元“0”和“1”;(3)将每一大组的信源符号进一步再分成两组,使划分后的两个组的概率之和近于相同,并又分别赋予一个二进制符号“0”和“1”;(4)如此重复,直至每个组只剩下一个信源符号为止;(5)信源符号所对应的码字即为费诺码。费诺码考虑了信源的统计特性,使经常出现的信源符号能对应码长短的编码字。显然,费诺码仍然是一种相当好的编码方法。但是,这种编码方法不一定能使短码得到充分利用。尤其当信源符号较多,并有一些符号概率分布很接近时,分两大组的组合方法就很多。可能某种分配结果,会出现后面小组的“概率和”相差较远,因而使平均码长增加,所以费诺码不一定是最佳码。费诺码的编码方法实际上是构造码树的一种方法,所以费诺码是一种即时码。​

编码输出

概率值

第一次分解

第二次分解

第三次分解

第四次分解

W1=0

0.40

0.40

0

 

 

 

W1=10

0.30

0.60

1

0.30

0

 

 

W1=111

0.15

 

 

0.30

1

0.15

1

 

W1=1101

0.10

 

 

 

 

0.15

0

0.10

1

W1=1100

0.05

 

 

 

 

 

 

0.05

0

 

代码部分:

#include<bits/stdc++.h>

using namespace std;

int main(){

​void Fenocode(double p[],int a ,int b,string c); // 函数声明 

​printf("请输入信源符号数:");

​int count;

​scanf("%d",&count); 

​double p[count];

​printf("请按顺序输入每个信源符号的概率:"); // 按顺序输入 可从小到大 亦可从大到小 

​for(int i = 0 ; i<count ; i++){

​​scanf("%lf",&p[i]);

​}

​string feno = ""; // 费诺编码结果 

​Fenocode(p,0,count-1,feno); 

​return 0;    

}

int cnt = 1; // 个数 

void Fenocode(double p[],int begin ,int end,string fenocode){

​double getSum(double p[],int a,int b); // 函数声明 

​// 边界条件 

​if(begin >= end){

​​// 输出结果 

​​cout<<"第";

​​cout<<cnt;

​​cout<<"个费诺编码为:"+fenocode<<endl; 

​​cnt++;

​​return;

​}

​// 找到分界值

​double sum = getSum(p,begin,end);

​int index = -1; // 初值设定 

​double minNum = sum; // 设定最小值 

​double tempSum = 0; // 前几个的和 

​for(int i = begin ; i <= end ; i++){

​​tempSum += p[i];

​​if(abs(sum-2*tempSum) < minNum){ 

​​​index = i; // 记录当前最小的值

​​​minNum = abs(sum-2*tempSum); // 更新最小值 

​​}

​}

​// 递归左边部分 

​Fenocode(p,begin,index,fenocode+'0'); // 左边添加0

​// 递归右边部分 

​Fenocode(p,index+1,end,fenocode+'1'); //右边添加1

}

double getSum(double p[] , int begin , int end){

​double sum = 0;

​for(int i = begin ; i <= end ; i++){

   ​sum += p[i];

​}

​return sum;

}

6c066eb8626e4088a308d0d775de5ec6.png

先算出平均码字长度K=∑p(ai)*ki=2.1

可得编码效率为:H(X)/K*100%=95.6%。

二、哈夫曼编码介绍:哈夫曼编码为分组编码,完全依据各字符出现的概率来构造码字。基本原理是基于二叉树的编码思想,所有可能的输入符号在哈夫曼书上对应一个节点,节点的位置就是该符号的哈夫曼编码。为了构造出唯一可译码,这些节点都是哈夫曼书上的终极节点,不再延伸,不会出现前缀码。

哈夫曼编码步骤:

1、将信源消息符号按其出现的概率大小依次排列

2、取两个概率最小的字母分别配以 0 和 1 两码元, 并将这两个概率相加作为一个新字母的概率, 与未分配的二进 符号的字母重新排队。

3、对重排后的两个概率最小符号重复步骤(2)的过程。

4、不断继续上述过程,直到最后两个符号配以 0 和 1 为止

5、从最后一级开始,向前返回得到各个信源符号所对应的码元序列, 即相应的码字。

例子:

信源符号

概率P

编码过程

编码

A1

0.40

0.4

0.4

0.6(0

1.0

1

A2

0.30

0.3

0.3(0

0.4(1

 

01

A3

0.15

0.15(0

0.3(1

 

 

001

A4

0.10(0

0.15(1

 

 

 

0000

A5

0.05(1

 

 

 

 

0001

 

先算出平均码字长度K=∑p(ai)*ki=2.05%

可得编码效率为:H(X)/K*100%=97.9%。

三、香农编码:香农编码是一种构造最佳码长的编码方法。香农编码是是采用信源符号的累计概率分布函数来分配字码的。香农编码是根据香农第一定理直接得出的,指出了平均码长与信息之间的关系,同时也指出了可以通过编码使平均码长达到极限值。香农第一定理是将原始信源符号转化为新的码符号,使码符号尽量服从等概分布,从而每个码符号所携带的信息量达到最大,进而可以用尽量少的码符号传输信源信息。香农编码属于不等长编码,通常将经常出现的消息变成短码,不经常出现的消息编成长码,从而提高通信效率。

其编码方法如下:

(1) 将信源消息符号按其出现的概率大小依次排列为。

(2) 确定满足下列不等式的整数码长为:

Ki=⌈-logP(ai) ⌉(其中⌈ ⌉表示向上取整)

(3) 为了编成唯一可译码,计算第i个消息的累加概率。

(4) 将累加概率变换成二进制数。

(5) 取二进制数的小数点后位即为该消息符号的二进制码字。

例子:

信源消息符号

符号概率p()

累加概率()

 

码字长度

码字

 

0.40

0

1.32

2

00

 

0.30

0.40

1.73

2

01

 

0.15

0.70

2.73

3

101

 

0.10

0.85

3.32

4

1101

 

0.05

0.95

4.32

5

11110

 

算出平均码字长度K=∑p(ai)*ki=2.5

可得编码效率为:H(X)/K*100%=80.32%。

综上

1、若仅论编码效率而言,哈夫曼码>费诺码>香农码。

2、费诺码和哈夫曼编码的方法是不唯一的。

3、香农编码拓展性较好,有唯一的编码。依据编码定理编码,具有重要的理论意义。考虑了信源的统计特性,使经常出现的信源符号对应较短的码字,使平均码长缩短,实现了信源压缩。

费诺编码考虑了信源的统计特性,使概率较大的信源符号能对应码长较短的码字,提升了香农编码的效率。但是编码效率不一定最高,当信源符号较多时,有一些符号概率比较接近,使分组变多码长也随之增加,编码过程复杂,有时短码未必能得到充分利用。

哈夫曼编码是最佳的,它虽然有不同编码方式,但最终平均码长相等,不影响编码效率和数据的压缩性能。

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值