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

霍夫曼编码是一种不等长非前缀编码方式,于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,一经查实,立即删除!

相关文章

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

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

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

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

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

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

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…

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

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

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

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

08-KNN手写数字识别

标签下载地址 文件内容备注train-images-idx3-ubyte.gz训练集图片&#xff1a;55000张训练图片&#xff0c;5000张验证图片train-labels-idx1-ubyte.gz训练集图片对应的数字标签t10k-images-idx3-ubyte.gz测试集图片&#xff1a;10000张图片t表示test&#xff0c;测试图片&…

MFC odbc访问远程数据库

首先&#xff0c;MFC通过ODBC访问数据库&#xff0c;主要使用两个类&#xff0c;一个是CDataBase&#xff0c;一个是CRecordset。第一个是用于建立数据库连接的&#xff0c;第二个是数据集&#xff0c;用来查询的。步骤如下&#xff1a;1.实例化一个CDataBase对象&#xff0c;并…

微机原理——扩展存储器设计

目录【1】存储器的层次结构【2】存储器的分类【3】SRAM1、基本原理&#xff1a;2、结构&#xff1a;3、芯片参数与引脚解读&#xff1a;4、CPU与SRAM的连接方式【4】DRAM1、基本原理&#xff1a;2、结构3、芯片引脚解读&#xff1a;【5】存储器系统设计【6】存储器扩展设计&…

09-CNN手写数字识别

CNN卷积神经网络的本质就是卷积运算 维度的调整&#xff1a; tf.reshape(imageInput,[-1,28,28,1]) imageInput为[None,784]&#xff0c;N行* 784维 调整为 M28行28列*1通道 即&#xff1a;二维转化为四维数据 参数一&#xff1a;等价于运算结果M 参数二&#xff1a;28 28 表示…

Opencv将处理后的视频保存出现的问题

问题描述&#xff1a; 代码运行过程中&#xff0c;imshow出来的每帧的效果图是正确的&#xff0c;但是按照网上的方法保存下来却是0kb&#xff0c;打开不了。 参考的网上的一些方法&#xff0c;均是失败的&#xff0c;具体原因我也不清楚&#xff1a; 1、例如我这样设置&#x…

黑白图片颜色反转并保存

将图像的黑白颜色反转并保存 import cv2 # opencv读取图像 img cv2.imread(rE:\Python-workspace\OpenCV\OpenCV/YY.png, 1) cv2.imshow(img, img) img_shape img.shape # 图像大小(565, 650, 3) print(img_shape) h img_shape[0] w img_shape[1] # 彩色图像转换为灰度图…

家猫WEB系统

现在只放源码在些.为它写应用很简单有空整理文档演示地址:jiamaocode.com/os/ 源码&#xff1a;http://jiamaocode.com/ProCts/2011/04/14/1918/1918.html转载于:https://www.cnblogs.com/jiamao/archive/2011/04/16/2018339.html

plesk 运行不了php,如何在Plesk中使用composer(使用其他版本的PHP运行Composer)

对于基于Plesk的服务器, composer的默认安装将使用系统安装的PHP版本, 而不使用Plesk所安装的任何版本。尽管Composer至少需要PHP 5.3.2, 但是当你尝试在需要特定版本PHP的项目中安装依赖项时, 就会出现问题。例如, 如果你有一个至少需要PHP 7.2的项目, 并且系统的默认PHP安装是…

Error: Flash Download failed - Target DLL has been cancelled

博主联系方式: QQ:1540984562 QQ交流群:892023501 群里会有往届的smarters和电赛选手,群里也会不时分享一些有用的资料,有问题可以在群里多问问。 由于换了新电脑,keil重装了下,然而之前的MCU的支持包没有安装,以及一些其他的问题,导致可以编译但是不能将程序烧录到单片…

我也谈委托与事件

虽然在博客园里面已经有很多关于C#委托和事件的文章&#xff0c;但是为了自己在学习的过程中&#xff0c;加深对委托的理解&#xff0c;我还是决定写一下自己的心得体会。以备他日在回来复习。委托&#xff08;delegate&#xff09;是一个类&#xff0c;但是这个类在声明的时候…

设计合理的实验方案来研究阳离子改性棉织物与未改性棉的染色动力学性能

染色动力学性能研究染色的什么问题?设计合理的实验方案来研究阳离子改性棉织物与未改性棉的染色动力学性能?并指出如何计算反映染色动力学的主要参数? 标准答案: 染色动力学研究染色速率问题。 为了研究阳离子改性棉纤维及未改性棉纤维对活性染料染色动力学性能,首先要测…