1. 熵编码概念

“熵”这一概念原本来自于化学和热力学,用于度量能量退化的指标,即熵越高,物体或系统的做功能力越低。后来香农将这一概念引入到信息论中,用于表示消息的平均信息量。信源的熵通常可以表示信源所发出信息的不确定性,即越是随机的、前后不相关的信息,其熵越高。

在信息论中,香农提出了信源编码定理。该定理说明了香农熵与信源符号概率之间的关系,说明信息的熵为信源无损编码后的平均码字长度的下限。任何的无损编码方法都不可能使编码后的平均码长小于香农熵,只能使其尽量接近。

基于此,对信源进行熵编码的基本思想,是使其前后的码字之间尽量更加随机,尽量减小前后的相关性,更加接近其信源的香农熵。这样在表示同样的信息量时所用的数据长度更短。

在实际使用中,常用的熵编码主要有变长编码和算术编码等方法。其中变长编码相对于算术编码较为简单,但平均压缩比可能略低。常见的变长编码方法有哈夫曼编码和香农-费诺编码等。

2. 熵编码的简单实现——哈夫曼编码

戴维·哈夫曼(David·A·Huffman)于1952年在麻省理工学院的罗伯特·费诺的指导下攻读博士学位时,发明了一种基于有序频率二叉树的编码方法,该方法的编码效率超过了他的导师和信息论之父香农的研究成果(香农-费诺编码),因此又称作“最优编码方法”。

哈夫曼编码时变长编码方法的一种,该方法完全依赖于码字出现的概率来构造整体平均长度最短的编码方法。进行哈夫曼编码的关键步骤是建立符合哈夫曼编码规则的二叉树,该树又称作哈夫曼树。

哈夫曼树是一种特殊的二叉树,其终端节点的个数与待编码的码元的个数等同,而且每个终端节点上都带有各自的权值。每个终端节点的路径长度乘以该节点的权值的总和称为整个二叉树的加权路径长度。在满足条件的各种二叉树中,该路径长度最短的二叉树即为哈夫曼树。

在使用哈夫曼编码执行对码元的实际编码过程时,码元的权值可设置为其概率值,那么可以根据其权值来构建哈夫曼树。我们假设使用哈夫曼编码对以下概率的码字进行编码:

码字 概率 
A 0.1 
B 0.1 
C 0.15 
D 0.2 
E 0.2 
F 0.25

根据概率表构建哈夫曼树的过程如下图所示:

最终我们可以得到如下图所示的哈夫曼树:

在哈夫曼树构建完成后,便可以得到每一个码元的哈夫曼编码的码字。具体方法是:从哈夫曼树的根节点开始遍历,直至每一个终端节点,当访问某个节点的左子树时赋予码字0,访问右子树时赋予一个码字1(反之亦可),直到遍历到终端节点时这一路径所代表的0和1的串便是该码元的哈夫曼编码码字。

例如上图的哈夫曼树,根节点访问左子树ABCF,赋予码字0;然后再访问左子树ABC,赋予码字0,此时整个码字为00,然后访问右子树得到终端节点C,赋予码字1,此时便可以得到C的哈夫曼编码码字001。以此规律,整个六个元素的码元集合的编码码表为:

  • A: 0000
  • B: 0001
  • C: 001
  • D: 10
  • E: 11
  • F: 01

从这个码表中还可以看出另外一个规律:哈夫曼编码的任意一个码字,都不可能是其他码字的前缀。因此通过哈夫曼编码的信息可以紧密排列连续传输,而不用担心解码时的歧义性。

3. 哈夫曼树的构建Demo

下面的程序段给出一个构建哈夫曼树,并生成对应码元的哈夫曼编码的过程:

#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <queue>
#include <vector>
#include <string>using namespace std;//每一个符号定义为一个结构体,包括字符和出现频次
typedef struct
{unsigned char   character;unsigned int    frequency;
} CharNode;static bool open_input_file(ifstream &input, const char *inputFileName)
{input.open(inputFileName);if (!input.is_open()){return false;}return true;
}struct MinHeapNode
{char data;unsigned int freq;MinHeapNode *left, *right;MinHeapNode(char data, unsigned freq){left = right = NULL;this->data = data;this->freq = freq;}
};
typedef struct MinHeapNode MinHeapNode;struct compare
{bool operator()(MinHeapNode* l, MinHeapNode *r){return (l->freq > r->freq);}
};static void get_huffman_code(MinHeapNode *root, string code)
{if (!root){return;}if (root->data != -1){cout << root->data << " : " << code << endl;;}get_huffman_code(root->left, code + "0");get_huffman_code(root->right, code + "1");
}int _tmain(int argc, _TCHAR* argv[])
{ifstream inputFile;if (!open_input_file(inputFile, "input.txt")){cout << "Error: opening input file failed!" << endl;return -1;}char buf = inputFile.get();CharNode nodeArr[256] = { { 0, 0 } };while (inputFile.good()){cout << buf;nodeArr[buf].character = buf;nodeArr[buf].frequency++;buf = inputFile.get();}cout << endl;priority_queue<MinHeapNode*, vector<MinHeapNode*>, compare>  minHeap;for (int idx = 0; idx < 256; idx++){if (nodeArr[idx].frequency > 0){cout << "Node " << idx << ": [" << nodeArr[idx].character << ", " << nodeArr[idx].frequency << "]" << endl;minHeap.push(new MinHeapNode(nodeArr[idx].character, nodeArr[idx].frequency));}}MinHeapNode *leftNode = NULL, *rightNode = NULL, *topNode = NULL;while (minHeap.size() != 1){leftNode = minHeap.top();minHeap.pop();rightNode = minHeap.top();minHeap.pop();topNode = new MinHeapNode(-1, leftNode->freq + rightNode->freq);topNode->left = leftNode;topNode->right = rightNode;minHeap.push(topNode);}get_huffman_code(topNode, "");inputFile.close();return 0;
}

程序的详细解释过程请到视频中观看。

七、 熵编码算法(1)——基础知识相关推荐

  1. 机器学习算法的基础知识

    机器学习算法的基础知识 1.评估指标 2.偏差与方差(过拟合与欠拟合) 3.正则化(解决过拟合) 4.梯度下降算法(算法优化方式) 5.数据不平衡 1.评估指标 预测值 0 1 实际 0 TN FP ...

  2. 运维小白的成长日记第四天-基础网络构建OSI七层模型-物理层基础知识

    运维小白的成长日记第四天- 基础网络构建OSI七层模型-物理层基础知识 网络运维的小白和想要加入网络运维的小伙伴们值得一看哦~ 今天是初识网络运维的第四天.希望能有志同道合的小伙伴一起讨论和学习,也希 ...

  3. 菜鸟学算法一基础知识篇

    菜鸟学算法<一>知识准备篇 刚刚上任,急着给兄弟们一点见面礼,嘿嘿 前言:论坛上有关算法分析的文章不少,也不少精品 但对于刚学CARACK来说,只是叹为观止 原因如下: 1.论坛高手如云, ...

  4. 数据结构基础:算法的基础知识笔记

    1.算法的概念 算法是问题求解过程中的精确描述,它为解决某一特定类型的问题规定了一个运算过程. 2.算法的特点 2.1 有穷性 一个算法必须在有穷的步骤结束后结束,并且每一步都在有穷时间内完成. 2. ...

  5. TCP系列39—拥塞控制—2、拥塞相关算法及基础知识

    原文:https://www.cnblogs.com/lshs/p/6038722.html 一.拥塞控制的相关算法 早期的TCP协议只有基于窗口的流控(flow control)机制而没有拥塞控制机 ...

  6. 七年级上册计算机基础知识教案,七年级上册信息技术教案

    中学信息技术课程的开展是为了提升学生们对信息技术学科的了解,下面是小编想跟大家分享的中学信息技术教案,欢迎大家浏览.一.指导思想与任务目标:初中阶段信息技术课程,使学生初步具备获取信息.传输信息.处理 ...

  7. PID算法的基础知识

    PID的含义 控制系统通常根据有没有反馈会分为开环系统和闭环系统,PID是一个闭环控制算法.因此要实现PID算法,必须在硬件上具有闭环控制,就是得有反馈.比如控制一个电机的转速,就得有一个测量转速的传 ...

  8. 机器学习中的数学(七)--凸优化的基础知识

    写在前面 <机器学习中的数学>系列主要列举了在机器学习中用到的较多的数学知识,包括微积分,线性代数,概率统计,信息论以及凸优化等等.本系列重在描述基本概念,并不在应用的方面的做深入的探讨, ...

  9. 数据结构之栈,栈是很多算法的基础知识,本文带你从0开始了解栈并手写一个栈

    栈(Stack) 一.目录 1.栈的基本介绍 2.栈的相关术语 3.栈的特点 4.栈实现的基本思路 5.栈的图解 6.数组实现栈的原码 7.栈的应用 二.正文 1.栈的基本介绍 栈的英文为Stack, ...

  10. 数据结构与算法学习——基础知识(一)

    数据结构与算法 线性结构和非线性结构 基本概念 线性结构 非线性结构 稀疏数组 基本概念 稀疏数组的处理方法 举例说明 应用实例 代码实例 队列 基本介绍 示意图 数组模拟队列 思路分析 代码实现 数 ...

最新文章

  1. 自动驾驶QNX,Linux,Autosar概述
  2. 80后博导当上双一流高校副校长:还是杰青获得者
  3. Collections 类
  4. java实现动态上传多个文件并解决文件重名问题
  5. 阿里云前端周刊 - 第 14 期
  6. java批量转换图片格式
  7. Apache阶段二-
  8. mos管结电容等效模型_【详解各元器件等效电路】电阻、电容、电感、二极管、MOS管!...
  9. abb变频器dp适配器说明书_PROFIBUS-DP与ABB变频器之间通讯设置步骤
  10. WinForm教程(一)App.config等配置文件
  11. java论文致谢_JAVA语言课程设计论文致谢范文
  12. pycocotools安装,简单易懂
  13. linux屏幕触碰事件,触摸屏中鼠标事件的捕获和传递及触摸屏的移植
  14. LeetCode 对角线遍历(找规律)
  15. S32K144时钟配置
  16. USACO 2018 January Contest
  17. Yolo 一文看懂目标检测
  18. python标准库复数运算包cmath
  19. 基于JSP的酒店登记预定系统的设计与实现
  20. 机电一体化T6113电气控制系统的设计(论文+DWG图纸)

热门文章

  1. 皮一皮:唉唉...这钱还没收呢...
  2. MySQL主从原理,基于快速学习一门技术的3种方式!
  3. 每日一皮:996标配工位原来是这样的!
  4. OpenJDK 14 性能保持提升,但 OpenJDK 8 仍是最强王者
  5. 帝国cms二次开发之文件夹的功能说明
  6. onnxruntime c++ 工程实例
  7. linux 常用命令总结
  8. pytorch maxpool和卷积尺寸问题
  9. 边缘检测算法及各自优缺点
  10. 使用python中的socket实现服务器和客户端,并完成图片的传输