赫夫曼\哈夫曼\霍夫曼编码 (Huffman Tree)
哈夫曼树
给定n个权值作为n的叶子结点,构造一棵二叉树,若带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree)。哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近。
哈夫曼编码(Huffman Coding)
又称霍夫曼编码,是一种编码方式,哈夫曼编码是可变字长编码(VLC)的一种。Huffman于1952年提出一种编码方法,该方法完全依据字符出现概率来构造异字头的平均长度最短的码字,有时称之为最佳编码,一般就叫做Huffman编码(有时也称为霍夫曼编码)。
应用举例
哈夫曼树─即最优二叉树,带权路径长度最小的二叉树,经常应用于数据压缩。 在计算机信息处理中,“哈夫曼编码”是一种一致性编码法(又称“熵编码法”),用于数据的无损耗压缩。这一术语是指使用一张特殊的编码表将源字符(例如某文件中的一个符号)进行编码。这张编码表的特殊之处在于,它是根据每一个源字符出现的估算概率而建立起来的(出现概率高的字符使用较短的编码,反之出现概率低的则使用较长的编码,这便使编码之后的字符串的平均期望长度降低,从而达到无损压缩数据的目的)。
构造Huffman tree


过程:
1、输入字符关键字以及对应的频率。
2、根据关键字的频率构造最优二叉树
(1)借助于STL的优先队列 :priority_queue<type, vector<type>,cmp>que; 其中type为优先队列的类型,比如说int, double, 也可以将结构体作为类型。vector它是一个多功能的,能够操作多种数据结构和算法的模板类和函数库。借助于vector可以很轻松的解决一些问题。cmp为定义的优先队列的出队规则,给出博客http://www.cnblogs.com/buptLizer/archive/2011/09/11/2173708.html大家可以参考来理解优先队列的使用。以及其中常用的操作que.pop(), que.push(), que.top(), que.size()等...
(2)构造最优二叉搜索树:在有了最优二叉搜索树的帮助之后,对于构建搜索树很容易。上面的图很清楚的讲解了构造的过程,每次取出频率最小的两个形成一个子树,将其频率相加之后再放入优先队列之中,直到队列中元素个数为0。在操作过程中需要遵守最优二叉搜索树的定义,左孩子小于父节点,右孩子大于父节点。
(3)递归遍历二叉树:遍历中只需要记住,向左遍历那么前缀码为0,向右为1.
亲测代码:
#include <bits/stdc++.h>
#define max_size 10010
char c[max_size];
double f[max_size]; using namespace std;
typedef struct node
{
char ch;
double freq;
node *lchild;
node *rchild;
node(char c=,double f=,node *l=NULL,node *r=NULL):
ch(c),freq(f),lchild(l),rchild(r) {}
};
typedef struct cmp
{
bool operator()(node*&a,node*&b)
{
return a->freq>b->freq;
}
};
node* createTree(int n)
{
priority_queue<node*,vector<node*>,cmp>que;
for(int i=; i<=n; i++)
{
cin>>c[i]>>f[i];
que.push(new node(c[i],f[i]));
}
while(que.size()>)
{
node *l=que.top();
que.pop();
node *r=que.top();
que.pop();
node *newnode=new node(,l->freq+r->freq,l,r);
que.push(newnode);
}
return que.top();
} void printInfo(const node *tree,string code)
{
if(tree->lchild==NULL&&tree->rchild==NULL)
{
cout<<tree->ch<<":"<<code<<" ";
return;
}
if(tree->lchild!=NULL)printInfo(tree->lchild,code+'');
if(tree->rchild!=NULL)printInfo(tree->rchild,code+'');
}
void deleteTree(node *tree)
{
if(tree->lchild!=NULL)deleteTree(tree->lchild);
if(tree->rchild!=NULL)deleteTree(tree->rchild);
delete(tree);
}
int main()
{
int n;
priority_queue<node*,vector<node*>,greater<node*> >que;
while(~scanf("%d",&n))
{
node *tree=createTree(n);
printf("Huffman code:\n");
printInfo(tree,"");
}
}
输入数据以及运行结果:

赫夫曼\哈夫曼\霍夫曼编码 (Huffman Tree)的更多相关文章
- opencv —— HoughLines、HoughLinesP 霍夫线变换原理(标准霍夫线变换、多尺度霍夫线变换、累积概率霍夫线变换)及直线检测
霍夫线变换的原理 一条直线在图像二维空间可由两个变量表示,有以下两种情况: ① 在笛卡尔坐标系中:可由参数斜率和截距(k,b)表示. ② 在极坐标系中:可由参数极经和极角(r,θ)表示. 对于霍夫线变 ...
- Java数据结构(十二)—— 霍夫曼树及霍夫曼编码
霍夫曼树 基本介绍和创建 基本介绍 又称哈夫曼树,赫夫曼树 给定n个权值作为n个叶子节点,构造一棵二叉树,若该树的带权路径长度(wpl)达到最小,称为最优二叉树 霍夫曼树是带权路径长度最短的树,权值较 ...
- word2vec 中的数学原理二 预备知识 霍夫曼树
主要参考: word2vec 中的数学原理详解 自己动手写 word2vec 编码的话,根是不记录在编码中的 这一篇主要讲的就是霍夫曼树(最优二叉树)和编码. ...
- opencv —— HoughCircles 霍夫圆变换原理及圆检测
霍夫圆变换原理 霍夫圆变换的基本原理与霍夫线变换(https://www.cnblogs.com/bjxqmy/p/12331656.html)大体类似. 对直线来说,一条直线能由极径极角(r,θ)表 ...
- OpenCV中的霍夫线变换和霍夫圆变换
一.霍夫线变换 霍夫线变换是OpenCv中一种寻找直线的方法,输入图像为边缘二值图. 原理: 一条直线在图像二维空间可由两个变量表示, 例如: 1.在 笛卡尔坐标系: 可由参数: (m,b) 斜率和截 ...
- C# 霍夫曼二叉树压缩算法实现
知道有的人比较懒,直接贴全部代码. 一开始一次性Code完了压缩部分代码.只调试了2,3次就成功了. 一次性写150行代码,没遇到什么bug的感觉还是蛮爽的. 写解压代码,才发现压缩代码有些细节问题. ...
- 基于python的二元霍夫曼编码译码详细设计
一.设计题目 对一幅BMP格式的灰度图像(个人证件照片)进行二元霍夫曼编码和译码 二.算法设计 (1)二元霍夫曼编码: ①:图像灰度处理: 利用python的PIL自带的灰度图像转换函数,首先将彩色图 ...
- 霍夫曼编码(Huffman Coding)
霍夫曼编码(Huffman Coding)是一种编码方法,霍夫曼编码是可变字长编码(VLC)的一种. 霍夫曼编码使用变长编码表对源符号(如文件中的一个字母)进行编码,其中变长编码表是通过一种评估来源符 ...
- CF 463A && 463B 贪心 && 463C 霍夫曼树 && 463D 树形dp && 463E 线段树
http://codeforces.com/contest/462 A:Appleman and Easy Task 要求是否全部的字符都挨着偶数个'o' #include <cstdio> ...
随机推荐
- Socket开发框架之消息的回调处理
在一般的Socket应用里面,很多时候数据的发送和接收是分开处理的,也就是我们发送一个消息,不知道这个请求消息什么时候得到应答消息,而且收到对应的应答消息的时候,如果操作界面的内容,也是需要特别处理的 ...
- C# 文件 文件夹
//判断文件夹(路径)是否存在 if (Directory.Exists(Path)) { } //获取文件大小 FileInfo file = new FileInfo(labOfPath); si ...
- Wojilu学习笔记 (01)
“我记录”开发框架(wojilu framework) 是 .net 平台下的综合开发框架,主要用于 web 方面的快速开发. 官方网址:http://www.wojilu.com源码托管网址: ht ...
- EasyUI使用tree方法生成树形结构加载两次的问题
html代码中利用class声明了easyui-tree,导致easyUI解析class代码的时候先解析class声明中的easyui-tree这样组件就请求了一次url:然后又调用js初始化代码请求 ...
- inner join on, left join on, right join on的区别与介绍
Table A aid adate 1 a1 2 a2 3 a3 TableB bid bdate 1 b1 2 b2 4 b4 两个表a,b相连接, ...
- iOS阶段学习第21天笔记(ARC内存管理-Copy-代理)
iOS学习(OC语言)知识点整理 一.OC 中的ARC内存管理 1)ARC中释放对象的内存原则:看这个对象有没有强引用指向它 2)strong:强引用,默认情况下的引用都是强引用 3) weak:弱引 ...
- 【转】数据库无关的GO语言ORM - hood
项目地址:https://github.com/eaigner/hood 这是一个极具美感的ORM库. 特性 链式的api 事务支持 迁移和名字空间生成 模型变量 模型时间 数据库方言接口 没有含糊的 ...
- springmvc(3)拦截器HandlerInterceptor源码的简单解析
其实拦截器就是我们的AOP编程.拦截器在我们的实际项目中实用性比较大的,比如:日志记录,权限过滤,身份验证,性能监控等等.下面就简单的来研究一下拦截器: public interface Handle ...
- Android事件处理机制
包括监听和回调两种机制. 1. 基于监听的事件处理: 事件监听包含三类对象,事件源,事件,事件监听器.Android的事件处理机制是一种委派式(Delegation)事件处理方式:普通组件(事件源)将 ...
- 算法:求幂(python版)
分别用迭代方法和递归方法实现求幂迭代方法的时间复杂度为O(n),空间复杂度为O(1)递归方法1的时间复杂度为O(logn),空间复杂度为O(logn)递归方法2的时间复杂度为O(n),空间复杂度为O( ...