霍夫码编码(一种不等长,非前缀编码方式)

霍夫曼编码是一种不等长非前缀编码方式,于1951年由MIT的霍夫曼提出。
用于对一串数字/符号编码获取最短的结果,获取最大的压缩效率。
特点:不等长非前缀

等长式编码

等长编码,意思是对出现的元素采用相同位数的序号进行标定,如下列所示:(这里我们采用三位)

假设有这样一串数据:

编码后的数据量:12 x 3bit=36bit.
思考:对5个数编码没必要每个数是同样的长度,只要五个字符对应的五个编码各自具有可区分性就行了。
非等长编码就是对不同的字符进行不同长度的编码

非等长式编码

如下列所示,我们采用非等长编码:

拿刚才说的字符串举例:

编码后的数据量是:3x2+1x5+2x3+41+14=25bit.
数据量减少了。
思考:如何确定哪种字符使用比较长的编码,哪种字符使用比较短的编码?
出现次数越多的字符我们使用更加短的编码,出现次数越少的字符我们使用更加长的编码。
现在可能又有疑问:为何不能像这样,B=0,A=1,类似这样,我们可以获取更加短的编码。
这里就要说到霍夫曼编码的另外一个特性:非前缀编码。

非前缀编码

以下图为例:

任何一个数据的编码都不与其他数据的编码的前缀重复。
如果B的编码为1,则和其他编码的前缀重复。
又如,C为11的话就和A、D、E的前缀重复了。
非前缀编码的优点:
在编码的时候其实和前缀编码一样,并没有什么简化的步骤。
但是在解码的时候将会有不同的效果:
假设,我们现在有一串数据:

解码得:
1110 110 1111 0 10 0 110 10 0 0 0 10
D A E B C B A C B B B C
已知码表,对编码后的信息进行解码,不需要知道断位信息,即可解码。也就是说我们不需要知道哪几个字符属于同一个就可以进行解码.

前缀编码

假设编码方式为如下。
前缀编码
当获取的数据串是:

11
在不知道断位信息的前提下,我们是无法对这串数据进行编码的。

霍夫曼编码

霍夫曼编码提供一种自动的方式获取非前缀非等长的编码,通过二叉树进行编码。

1)将信源符号的概率按减小的顺序排队。
2)把两个最小的概率相加,并继续这一步骤,始终将较高的概率分支放在右边,直到最后变成概率1。
3)画出由概率1处到每个信源符号的路径,顺序记下沿路径的0和1,所得就是该符号的霍夫曼码字。
4)将每对组合的左边一个指定为0,右边一个指定为1(或相反)。

例子讲解:
1、计算每个字符出现次数

input出现次数
B10
A8
C3
D4
E5

2、把出现次数(概率)最小的两个相加,并作为左右子树,重复此过程,直到概率值为1
1
第一次:将概率最低值3和4相加,组合成7:
1
第二次:将最低值5和7相加,组合成12:
2
第三次:将8和10相加,组合成18:
3
第四次:将最低值12和18相加,结束组合:
4
3 将每个二叉树的左边指定为0,右边指定为1
3
4 沿二叉树顶部到每个字符路径,获得每个符号的编码

output编码
B11
A10
C010
D011
E00

霍夫曼编码的缺陷

(1)哈夫曼编码所形成的码字不是复唯一的,但编码效率是唯一的在对最小的两个概率符号赋值时,可以规定为大的为“1”、小的为“0”,反之也可以。如果两个符号的出现概率相等时,排列时无论哪个在前都是可以的,所以哈夫曼所构造的码字不是唯一的,对于制同一个信息源,无论上述的前后顺序如何排列,它的平均码长是不会改变的,所以编码效率是唯一的。
(2)只有当信息源各符号出现的概率很不平百均的时候,哈夫曼编码的效果才明显。
(3)哈夫曼编码必须精确地统度计出原始文件中每个符号的出现频率,如果没有这些精确的统计,将达不到预期的压缩效果。霍夫曼编通常要经过两遍操作,第一遍进行统计,第二遍产生编码,所以编码速度相对慢。另外实现的电路复杂,各问种长度的编码的译码过程也是较复杂的,因此解压缩的过程也比较慢。
(4)哈夫曼编码只能用整数来表示单个符号而不能用小数,这很大程度上限制了压缩效果。
(5)哈夫曼所有位都是合在一起的,如果改动其中一位就可以答使其数据变得面目全非

编程实现

代码摘自博客:霍夫曼编码(Huffman Coding)

#include <stdio.h>
#include<stdlib.h>
#include<string>
#include <iostream>#define MAXBIT      100
#define MAXVALUE  10000
#define MAXLEAF     30
#define MAXNODE    MAXLEAF*2 -1typedef struct 
{int bit[MAXBIT];int start;
} HCodeType;        /* 编码结构体 */
typedef struct
{int weight;int parent;int lchild;int rchild;char value;
} HNodeType;        /* 结点结构体 *//* 构造一颗哈夫曼树 */
void HuffmanTree (HNodeType HuffNode[MAXNODE],  int n)
{ /* i、j: 循环变量,m1、m2:构造哈夫曼树不同过程中两个最小权值结点的权值,x1、x2:构造哈夫曼树不同过程中两个最小权值结点在数组中的序号。*/int i, j, m1, m2, x1, x2;/* 初始化存放哈夫曼树数组 HuffNode[] 中的结点 */for (i=0; i<2*n-1; i++){HuffNode[i].weight = 0;//权值 HuffNode[i].parent =-1;HuffNode[i].lchild =-1;HuffNode[i].rchild =-1;HuffNode[i].value=' '; //实际值,可根据情况替换为字母  } /* end for *//* 输入 n 个叶子结点的权值 */for (i=0; i<n; i++){printf ("Please input char of leaf node: ", i);scanf ("%c",&HuffNode[i].value);getchar();} /* end for */for (i=0; i<n; i++){printf ("Please input  weight of leaf node: ", i);scanf ("%d",&HuffNode[i].weight);getchar();} /* end for *//* 循环构造 Huffman 树 */for (i=0; i<n-1; i++){m1=m2=MAXVALUE;     /* m1、m2中存放两个无父结点且结点权值最小的两个结点 */x1=x2=0;/* 找出所有结点中权值最小、无父结点的两个结点,并合并之为一颗二叉树 */for (j=0; j<n+i; j++){if (HuffNode[j].weight < m1 && HuffNode[j].parent==-1){m2=m1; x2=x1; m1=HuffNode[j].weight;x1=j;}else if (HuffNode[j].weight < m2 && HuffNode[j].parent==-1){m2=HuffNode[j].weight;x2=j;}} /* end for *//* 设置找到的两个子结点 x1、x2 的父结点信息 */HuffNode[x1].parent  = n+i;HuffNode[x2].parent  = n+i;HuffNode[n+i].weight = HuffNode[x1].weight + HuffNode[x2].weight;HuffNode[n+i].lchild = x1;HuffNode[n+i].rchild = x2;printf ("x1.weight and x2.weight in round %d: %d, %d\n", i+1, HuffNode[x1].weight, HuffNode[x2].weight);  /* 用于测试 */printf ("\n");} /* end for */} /* end HuffmanTree *///解码 
void decodeing(char string[],HNodeType Buf[],int Num)
{int i,tmp=0,code[1024];int m=2*Num-1;char *nump;char num[1024];for(i=0;i<strlen(string);i++){if(string[i]=='0')num[i]=0;        elsenum[i]=1;                    } i=0;nump=&num[0];while(nump<(&num[strlen(string)])){tmp=m-1;while((Buf[tmp].lchild!=-1)&&(Buf[tmp].rchild!=-1)){if(*nump==0){tmp=Buf[tmp].lchild ;          } else tmp=Buf[tmp].rchild;nump++;} printf("%c",Buf[tmp].value);                                  }
}int main(void)
{HNodeType HuffNode[MAXNODE];            /* 定义一个结点结构体数组 */HCodeType HuffCode[MAXLEAF],  cd;       /* 定义一个编码结构体数组, 同时定义一个临时变量来存放求解编码时的信息 */int i, j, c, p, n;char pp[100];printf ("Please input n:\n");scanf ("%d", &n);HuffmanTree (HuffNode, n);for (i=0; i < n; i++){cd.start = n-1;c = i;p = HuffNode[c].parent;while (p != -1)   /* 父结点存在 */{if (HuffNode[p].lchild == c)cd.bit[cd.start] = 0;elsecd.bit[cd.start] = 1;cd.start--;        /* 求编码的低一位 */c=p;                    p=HuffNode[c].parent;    /* 设置下一循环条件 */} /* end while *//* 保存求出的每个叶结点的哈夫曼编码和编码的起始位 */for (j=cd.start+1; j<n; j++){ HuffCode[i].bit[j] = cd.bit[j];}HuffCode[i].start = cd.start;} /* end for *//* 输出已保存好的所有存在编码的哈夫曼编码 */for (i=0; i<n; i++){printf ("%d 's Huffman code is: ", i);for (j=HuffCode[i].start+1; j < n; j++){printf ("%d", HuffCode[i].bit[j]);}printf(" start:%d",HuffCode[i].start);printf ("\n");}printf("Decoding?Please Enter code:\n");scanf("%s",&pp);decodeing(pp,HuffNode,n);getchar();return 0;
}

结果
Reference:

霍夫曼编码(HuffmanCoding)
哈夫曼编码和二进制编码优缺点比较
《数字图像处理PPT.李竹版》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/378542.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

php调用shell脚本安全,从PHP调用的shell脚本问题

TLDR;我有一个shell脚本,从命令行运行时工作正常,但如果从PHP脚本中调用(通过Web访问)则不行.在这两种情况下,主叫用户都是www-data.线路失败是这样的&#xff1a;openssl genrsa -des3 -out certs/$PCODE.key -passout env:PASSPHRASE 2048为什么会这样&#xff1f;我该怎么调…

linux 运维基础问题_Linux基础能力问题和解答

linux 运维基础问题This section contains Aptitude Questions and Answers on Linux Basics. 本节包含有关Linux基础知识的 Aptitude问答。 1) There are the following statements that are given below, which of them are correct about Linux? Linux is system software…

JS 获取浏览器信息,给出友情提示,避免部分兼容性问题

最近在做webform,浏览器兼容是个问题,这里我收集了一些获取浏览器信息的资料,可以给一些用户使用时,提示浏览器版本过低,让升级版本用. 这样会给开发的我们,省下很多用来调试兼容性的时间和精力. 本人就是这样想的 ~  检测浏览器及版本使用 JavaScript 检测关于访问者的浏览器…

两栏 三栏的css

三栏格局 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns"http://www.w3.org/1999/xhtml" xml:lang"zh" lang"zh"><head pro…

06-机器学习(Haar+Adaboost实现人脸、人眼检测)

机器学习是什么? 机器学习训练样本特征分类器&#xff0c;通过让机器学习的方式&#xff0c;来达到某种功能的过程 深度学习是什么&#xff1f; 深度学习海量的学习样本人工神经网络 机器学习需要&#xff1a;样本、特征、分类器、对训练后的数据进行预测或检验 人脸样本haar…

php xml表格形式输出,PHP XML如何输出nice格式

这里是代码&#xff1a;$doc new DomDocument(1.0);// create root node$root $doc->createElement(root);$root $doc->appendChild($root);$signed_values array(a > eee, b > sd, c > df);// process one row at a timeforeach ($signed_values as $key &…

Opencv实战【3】——图像修复与图像锐化(darling in the franxx)

目录前言图像修复图像锐化darling in the franxx图片总结前言 前天&#xff0c;在群里看见有人发了这张表情包&#xff1a; 感觉女主有点好看&#xff0c;然后问室友是啥番剧&#xff08;darling in the franxx&#xff09;&#xff0c;然后就去补番了&#xff0c;然后从晚上…

python 示例_Python date isoweekday()方法与示例

python 示例Python date.isoweekday()方法 (Python date.isoweekday() Method) date.isoweekday() method is used to manipulate objects of date class of module datetime. date.isoweekday()方法用于处理模块日期时间的日期类的对象。 It uses a date class object and r…

07-机器学习(Hog+SVM实现小狮子识别)

一、SVM支持向量机 什么是SVM支持向量机&#xff1f; SVM支持向量机本质仍是一个分类器&#xff0c;其核心为寻求一个最优超平面最终实现分类&#xff0c;实现分类问题 在寻求超平面的时候有多种方式&#xff0c;可以使用若干条直线或曲线进行分类&#xff0c;这里使用的是直线…

Net Remoting基础篇

一、Remoting基础 什么是Remoting&#xff0c;简而言之&#xff0c;我们可以将其看作是一种分布式处理方式。从微软的产品角度来看&#xff0c;可以说Remoting就是DCOM的一种升 级&#xff0c;它改善了很多功能&#xff0c;并极好的融合到.Net平台下。Microsoft .NET Remoting …

Maven3.0.5代理nexus

Nexus简介 Nexus是Sonatype推出的强大Maven仓库管理器产品&#xff0c;要比以前TSS上介绍的Artifactory要好使用的多&#xff0c;也是一个拆箱即用的Java App&#xff0c;内嵌Jetty容器和Java Wrapper做Windows服务&#xff0c;安装简单到解压然后双击install即可。更详细的帮助…

8253译码电路设计以及初始化编程讲解

先验知识回顾&#xff1a;知识点不清晰的时候可以查询相关知识点。 https://blog.csdn.net/qq_42604176/article/details/105810973 需掌握的主要知识点 1、译码电路设计 2、初始化编程 例题1 在以 8086构成的最大方式系统中&#xff0c;有一片8254的端口地址分别为301H、3…

java安卓写文件路径,如何使用gradle作为构建系统,平台Android配置Protobuf(Java)文件的输出路径?...

我正在努力解决以下问题&#xff1a;我有2个基于maven的java项目和1个基于gradle的Android项目 . 布局如下&#xff1a;Workspace/├── MavenProj1/├── MavenProj2/├── AndroidGradleProject1/├── Protos/所有这些的包结构很常见&#xff0c;比方说 com.example.* 所…

Java System类exit()方法及示例

系统类exit()方法 (System class exit() method) exit() method is available in java.lang package. exit()方法在java.lang包中可用。 exit() method is used to exit the currently running JVM (Java Virtual Machine). exit()方法用于退出当前正在运行的JVM(Java虚拟机)。…

基于图像处理的数码印花喷墨墨滴形状规范的研究(Python+OpenCV+Mysql)

大体思路&#xff1a;由于墨滴的不同参数会对墨滴的形态产生一定的影响&#xff0c;故如果通过研究墨滴的形态则通过海量的数据就可以大概确定墨滴的各项参数指标的范围。通过OpenCV对墨滴的喷出的形状进行图像处理&#xff0c;对墨滴图像进行一系列的分析&#xff0c;通过一系…

ASP.NET 主题(Themes)FAQ

1、主题是什么 主题由一组元素组成&#xff1a;外观、级联样式表 (CSS)、图像和其他资源。主题将至少包含外观。主题是在网站或 Web 服务器上的特殊目录中定义的。主题是一组Web Control的属性设置的集合&#xff0c;提供一种简单的方法设置控件的样式属性。 主题只在Web Contr…

Head First HTML与CSS、XHTML++笔记(第四章 WEB镇之旅 第五章 认识媒体)

第四章 链接&#xff08;详解<a>元素&#xff09; 目标锚 在目标位置 <h2><a id"chai">contentTest</a></h2> 在需要链接位置 <a href"index.html#chai">See</a> 链接到自身的目标锚 <a href"#top"…

Opencv实战【4】——图片动漫化处理

博主联系方式&#xff1a; QQ:1540984562 微信&#xff1a;wxid_nz49532kbh9u22 QQ交流群&#xff1a;750313950 目录动漫化风格的特点处理手段代码实现效果总结动漫化风格的特点 &#xff08;1&#xff09;动漫中的细节相对少&#xff1b; &#xff08;2&#xff09;动漫中的边…

nextshort_Java扫描仪的nextShort()方法与示例

nextshort扫描器类的nextShort()方法 (Scanner Class nextShort() method) Syntax: 句法&#xff1a; public short nextShort();public short nextShort(int rad);nextShort() method is available in java.util package. nextShort()方法在java.util包中可用。 nextShort() …

php 生成css文件怎么打开,php生成html文件的多种步骤介绍

//定义日期函数functiongetdatetime(){$datetimegetdate();$strReturn$datetime["year"]."-";$strReturn$strReturn.$datetime["mon"]."-";$strReturn$strReturn.$datetime["mday"];return$strReturn;}//定义时间函数(文件名…