霍夫曼编译码的Matlab代码实现

霍夫曼编码的简介

哈夫曼编码(Huffman Coding),又称霍夫曼编码,是一种编码方式,哈夫曼编码是可变字长编码(VLC)的一种。Huffman于1952年提出一种编码方法,该方法完全依据字符出现概率来构造异字头的平均长度最短的码字,有时称之为最佳编码,一般就叫做Huffman编码(有时也称为霍夫曼编码)。

摘自百度百科:链接

霍夫曼编码的原理

这里不再赘述,直接粘过来

赫夫曼树(Huffman Tree),又称最优二叉树,是一类带权路径长度最短的树。假设有n个权值{w1,w2,…,wn},如果构造一棵有n个叶子节点的二叉树,而这n个叶子节点的权值是{w1,w2,…,wn},则所构造出的带权路径长度最小的二叉树就被称为赫夫曼树。

这里补充下树的带权路径长度的概念。树的带权路径长度指树中所有叶子节点到根节点的路径长度与该叶子节点权值的乘积之和,如果在一棵二叉树中共有n个叶子节点,用Wi表示第i个叶子节点的权值,Li表示第i个也叶子节点到根节点的路径长度,则该二叉树的带权路径长度 WPL=W1L1 + W2L2 + … Wn*Ln。

根据节点的个数以及权值的不同,赫夫曼树的形状也各不相同,赫夫曼树具有如下特性:

对于同一组权值,所能得到的赫夫曼树不一定是唯一的。

赫夫曼树的左右子树可以互换,因为这并不影响树的带权路径长度。

带权值的节点都是叶子节点,不带权值的节点都是某棵子二叉树的根节点。

权值越大的节点越靠近赫夫曼树的根节点,权值越小的节点越远离赫夫曼树的根节点。

赫夫曼树中只有叶子节点和度为2的节点,没有度为1的节点。

一棵有n个叶子节点的赫夫曼树共有2n-1个节点。

霍夫曼Tree的构建

赫夫曼树的构建步骤如下:

1、将给定的n个权值看做n棵只有根节点(无左右孩子)的二叉树,组成一个集合HT,每棵树的权值为该节点的权值。

2、从集合HT中选出2棵权值最小的二叉树,组成一棵新的二叉树,其权值为这2棵二叉树的权值之和。

3、将步骤2中选出的2棵二叉树从集合HT中删去,同时将步骤2中新得到的二叉树加入到集合HT中。

4、重复步骤2和步骤3,直到集合HT中只含一棵树,这棵树便是赫夫曼树。

由右边的霍夫曼Tree得到左边的霍夫曼表:

霍夫曼编码

由于霍夫曼Tree已经建立好了,接下来就进行霍夫曼编码,在由叶子结点到根节点的过程中,如果经过左子树,则编为0,如果经过右子树则变为1,编码所在的层数越小,编码的位次就越高,具体形式请参看:哈夫曼树及哈夫曼编码详解【完整版代码】的Huffman编码部分。

霍夫曼编码Matlab代码实现

代码思路:

1、首先保存输入各权重的值,以数组的形式输入。

2、得到各个值的权重值之后,建立霍夫曼树,其实我建立的并不是霍夫曼Tree,而是上图中左边的霍夫曼表,其实霍夫曼表就是由霍夫曼Tree直接得到的,本质二者没有差别,只是表现的形式不同而已。

3、利用得到的霍夫曼Tree进行霍夫曼编码,首先我创建了与输入值的个数相等的空字符数组,用与进行霍夫曼编码,说白了就是为了存“0”和“1”。再从叶子结点到根节点的过程中,如果是左子树,则在该数组前面连接一个字符“0”,如果是右子树,则在该数组前面连接一个字符“1”,直到根节点为止,这样就得到了一个数的编码值。

4、计算平均码长。

5、计算信源熵。

6、计算编码效率。

直接上代码:

clear

p=input('输入信源概率分布:\n');

[~,n]=size(p);%得到编码个数

HT=zeros(2*n-1,4);%构造霍夫曼树

for i=1:n

HT(i,1)=p(i);

end

HT;%第一列为个数的权重值 1~4列分别为 权重 父节点 左孩子 右孩子

HT0=HT;

%构建霍夫曼树

for i=1:n-1

a=HT0(:,1);

[b,l]=sort(a,'descend');

s=b(n-i+1)+b(n-i);%选取两个最小值进行求和 大 小

HT0(n+i,1)=s;%将求和后的数放进霍夫曼树的父节点上

HT0(l(n-i+1),1)=0;%将两个最小值删除,清零

HT0(l(n-i),1)=0;%将两个最小值删除,清零

HT0(l(n-i+1),2)=n+i;%两个最小值的父节点

HT0(l(n-i),2)=n+i;%两个最小值的父节点

HT0(n+i,3)=l(n-i+1);%父节点的左孩子

HT0(n+i,4)=l(n-i);%父节点的右孩子

%重构霍夫曼树

HT(n+i,1)=s;

HT(l(n-i+1),2)=n+i;

HT(l(n-i),2)=n+i;

HT(n+i,3)=l(n-i+1);

HT(n+i,4)=l(n-i);

end

HT;%去掉分号可查看霍夫曼树

%字符数组,用于生成霍夫曼码

a={;};

for i=1:n

a{1,i}=' ';

end

%霍夫曼编码

for i=1:n

f=i;

while(HT(f,2)~=0)%直到父节点为根结点时,编码完成

q=HT(f,2);%取出叶子结点的父节点的值

if HT(q,3)==f

a{i}=strcat('0',a{i});%若为左孩子,则编为0

else

a{i}=strcat('1',a{i});%若为右孩子,则编为1

end

f=q;%继续寻找父节点的节点

end

end

fprintf('各分布概率的霍夫曼编码为:\n');

for i=1:n

fprintf( '%f的编码为:"%s"\n' ,HT(i,1),a{i});

end

%计算平均码长

l=[];

L_1=0;

for i=1:n

l(i)=length(a{i});

L_1=l(i)*HT(i,1)+L_1;

end

fprintf('平均码长为:%f \n',L_1);

%计算信源熵

Hx=0;

for i=1:n

Hx=-HT(i,1).*log2(HT(i,1))+Hx;

end

fprintf('信源熵为:%f \n',Hx);

%计算编码效率

M=Hx/L_1;

fprintf('编码效率为:%f \n',M);

为了更好地理解我就拿刚才的那个图举个例子:

脚本文件运行之后:

首先输入:(注意,此代码在输入权重时,必须用方括号阔起来)

输入信源概率分布:

[0.4 0.3 0.15 0.05 0.04 0.03 0.03]

如果运行没有问题的话,结果应该为:

各分布概率的霍夫曼编码为:

0.400000的编码为:"0"

0.300000的编码为:"11"

0.150000的编码为:"101"

0.050000的编码为:"10011"

0.040000的编码为:"10010"

0.030000的编码为:"10001"

0.030000的编码为:"10000"

平均码长为:2.200000

信源熵为:2.165790

编码效率为:0.984450

霍夫曼译码

代码思路:

1、首先输入各个值的权重值,并保存。

2、构建霍夫曼Tree。

3、每次输入一个值的编码值,得到该编码的权重值。

上代码:

clear

p=input('输入信源概率分布:\n');

[~,n]=size(p);%得到编码个数

HT=zeros(2*n-1,4);%构造霍夫曼树

for i=1:n

HT(i,1)=p(i);

end

HT;%第一列为个数的权重值 1~4列分别为 权重 父节点 左孩子 右孩子

HT0=HT;

%构建霍夫曼树

for i=1:n-1

a=HT0(:,1);

[b,l]=sort(a,'descend');

s=b(n-i+1)+b(n-i);%选取两个最小值进行求和 大 小

HT0(n+i,1)=s;%将求和后的数放进霍夫曼树的父节点上

HT0(l(n-i+1),1)=0;%将两个最小值删除,清零

HT0(l(n-i),1)=0;%将两个最小值删除,清零

HT0(l(n-i+1),2)=n+i;%两个最小值的父节点

HT0(l(n-i),2)=n+i;%两个最小值的父节点

HT0(n+i,3)=l(n-i+1);%父节点的左孩子

HT0(n+i,4)=l(n-i);%父节点的右孩子

%重构霍夫曼树

HT(n+i,1)=s;

HT(l(n-i+1),2)=n+i;

HT(l(n-i),2)=n+i;

HT(n+i,3)=l(n-i+1);

HT(n+i,4)=l(n-i);

end

HT;

%霍夫曼解码

t=[];%存储二进制报文

t=input('输入二进制报文(注意输入各数之间用空格或者逗号隔开并用方括号阔起来,例:[1 0 1]):\n');%输入二进制报文

[~,v]=size(t);%得到二进制报文的长度

f=2*n-1;

i=1;

while(HT(f,3)||HT(f,4)||(i<=v))

if(t(i)==0)%从根节点出发,读入0则走向左孩子,读入1则走向右孩子

q=HT(f,3);%读入0则走向左孩子

f=q;

else

q=HT(f,4);%读入1则走向右孩子

f=q;

end

i=i+1;%读取下一个二进制报文

end

fprintf('输出对应的概率值为:\n');

disp(HT(f,1));%输出对应的概率值

还是那刚才的那个表举例:

脚本文件运行之后:

输入:

输入信源概率分布:

[0.4 0.3 0.15 0.05 0.04 0.03 0.03]

再次提示输入:

输入二进制报文(注意输入各数之间用空格或者逗号隔开并用方括号阔起来,例:[1 0 1]):

[1 0 0 0 0]

输出:

输出对应的概率值为:

0.0300

我又对霍夫曼编译码进行了整合:

代码如下:

p=input('输入信源概率分布:\n');

%function Huffman_coding_decoding(p)

[~,n]=size(p);%得到编码个数

HT=zeros(2*n-1,4);%构造霍夫曼树

for i=1:n

HT(i,1)=p(i);

end

HT;%第一列为个数的权重值 1~4列分别为 权重 父节点 左孩子 右孩子

HT0=HT;

%构建霍夫曼树

for i=1:n-1

a=HT0(:,1);

[b,l]=sort(a,'descend');

s=b(n-i+1)+b(n-i);%选取两个最小值进行求和 大 小

HT0(n+i,1)=s;%将求和后的数放进霍夫曼树的父节点上

HT0(l(n-i+1),1)=0;%将两个最小值删除,清零

HT0(l(n-i),1)=0;%将两个最小值删除,清零

HT0(l(n-i+1),2)=n+i;%两个最小值的父节点

HT0(l(n-i),2)=n+i;%两个最小值的父节点

HT0(n+i,3)=l(n-i+1);%父节点的左孩子

HT0(n+i,4)=l(n-i);%父节点的右孩子

%重构霍夫曼树

HT(n+i,1)=s;

HT(l(n-i+1),2)=n+i;

HT(l(n-i),2)=n+i;

HT(n+i,3)=l(n-i+1);

HT(n+i,4)=l(n-i);

end

HT;

while(1)

y=input('请选择需要的进行的操作:\n 1.编码\n 2.解码\n 3.退出\n');

if y==1

Huffman_coding(p);

end

if y==2

huffman_decoding(p);

end

if y==3

break;

end

end

把编码和译码分成了两个不同函数进行调用:

脚本文件运行成功后:

输入信源概率分布:

[0.4 0.3 0.15 0.05 0.04 0.03 0.03]

请选择需要的进行的操作:

1.编码

2.解码

3.退出

注意!!!霍夫曼编译码是建立在同一个霍夫曼Tree下的。

如有不足请多指教。

如果原理看不明白,建议去B站看 青岛大学–王卓有关霍夫曼编码的视频讲解,老师是用C实现的霍夫曼编译码,原理懂了,什么语言实现都无所谓。让我们一起加油吧。

2020.1.28 by iNBC from SDUT

qq_40700822

发布了1 篇原创文章 · 获赞 0 · 访问量 37

私信

关注

标签:编码,end,HT,编译,Matlab,HT0,霍夫曼,节点

来源: https://blog.csdn.net/qq_40700822/article/details/104100028

matlab霍夫曼吗仿真,霍夫曼编译码的Matlab代码实现相关推荐

  1. 码长6075的qc-ldpc编译码的MATLAB误码率仿真

    1.算法简介 为满足高的数据需求,提出一种新的QC-LDPC码.该校验矩阵的校验部分为近似下三角结构,上对角线下面的非零元素可以任意放置,因此是一种半确定的结构.这种结构的码设计灵活,性能也极高.通过 ...

  2. LDPC的信道编译码的matlab仿真——LDPC译码最小和和归一化最小和

    1.问题描述: LDPC的信道编译码的matlab仿真--LDPC译码最小和和归一化最小和 2.部分程序: clc; clear all; load H; D=H(1:675,5401:6075); ...

  3. matlab浮点数求绝对值_MATLAB仿真阵列天线切比雪夫综合法(附代码)

    来源:cnblogs 在<自适应天线与相控阵>这门课中,了解到了关于理想低副瓣阵列设计的一些方法,其中切比雪夫等副瓣阵列设计方法是一种基础的方法,故将其设计流程写成maltab程序供以后学 ...

  4. 算法导论——贪心算法:哈夫曼编码(霍夫曼编码)

    2019独角兽企业重金招聘Python工程师标准>>> package org.loda.greedy;import org.junit.Test; import org.loda. ...

  5. 【polar码】polar编译码以及SC译码算法的matlab仿真验证,对比不同编码码率的误码率性能

    目录 1.polar编译码以及SC译码理论概述 2.matlab编程实现 3.仿真验证 1.polar编译码以及SC译码理论概述 Polar编译码(Polar coding)是一种新型的编码技术,由E ...

  6. matlab 卷积码函数,MATLAB实现卷积码编译码-.doc

    MATLAB实现卷积码编译码- 本科生毕业论文(设计) 题 目: 作者姓名: 学 号: 单 位: 指导教师: 年 月 日 目 录 前言1 1. 纠错码基本理论2 1.1纠错码基本理论2 1.1.1纠错 ...

  7. labview 霍夫曼树_哈夫曼树编码实验报告_信息论与编码实验2 实验报告_信息论与编码报告...

    huffman编码C语言实验报告 今日推荐 180份文档 2014...4页 1下载券 安卓版100 doors 2攻略1... 3页 1下载券 <逃脱本色>doors....语文教育实习 ...

  8. python哈夫曼树_python霍夫曼树

    class Node(): data=0 left=None right=None father=None def __init__(self,data,left,right): self.data= ...

  9. 霍夫曼树(赫夫曼树、哈夫曼树)

    霍夫曼树:给定n个权值做为n个叶子节点,若该树的带权路径长度达到最小,这棵树为最优二叉树,也称赫夫曼树. 霍夫曼树中的几个概念 路径和路径长度 一棵树中,一个节点往下可以达到的孩子或孙子节点之间的通路 ...

  10. 哈夫曼树(霍夫曼树)-详解

    哈夫曼树(霍夫曼树)-详解 哈夫曼树(霍夫曼树)-详解 何为权值?我们看下百度百科的解释. 何为路径? 何为路径长度? 何为树的路径长度? 何为结点的带权路径长度? 何为树的带权路径长度(WPL)? ...

最新文章

  1. mongocollection java_mongodb与java的整合
  2. 全球及中国液化天然气(LNG)行业建设规模现状及十四五产业规划报告2021年版
  3. linux dns chroot,系统运维|在 CentOS7.0 上搭建 Chroot 的 Bind DNS 服务器
  4. HBase性能优化方法总结(三):读表操作
  5. java模仿qq好友面板的布局(BoxLayout问题)
  6. sql server 2005 T-SQL BACKUP CERTIFICATE (Transact-SQL)
  7. linux账号和权限管理思维导图,Linux系统支持的思维导图软件有哪些?
  8. 738. 单调递增的数字(JavaScript)
  9. python匿名函数_Python匿名函数
  10. l7sa008b故障代码_Robertshaw 365-A8振动开关故障探测器
  11. HYSBZ 1406 密码箱
  12. 酷家乐服务网格与Serverless落地情况
  13. 最简单华为设备怎么无需Root激活XPOSED框架
  14. 世界第一台电子计算机到底是谁?
  15. 段错误(核心已转储)的问题原因
  16. 新手淘宝卖家不知道如何运营店铺,精细化运营让你走的更远
  17. 异常处理——NullPointerException
  18. UI设计入门知识大全!零基础小白必看
  19. 纯html5语言编写的动画,8个纯CSS3制作的动画应用及源码
  20. 数字化企业云平台的Cloud Native12原则

热门文章

  1. ubuntu 22.0 不能调节屏幕亮度
  2. 爬虫链家7万条数据,告诉你二手房市场的现状
  3. 你以为链家只是一个中介,但其实……
  4. 年轻人千万别让老司机把你带到坑里
  5. eCognition软件中ESP2插件的下载与安装
  6. BUAA_4:Kevin·Feng的正确@姿势
  7. U盘打不开的常见情况和解决方法
  8. adb命令模拟按键事件 KeyCode
  9. 为什么传输前要进行编码与调制
  10. python transforms_2.2 图像预处理——transforms(笔记)