Huffman 编码树

Huffman 编码树Huffman 编码树像 SCAII 这样即那个每个字符表示为一个 7 为二进制的序列的编码方式称为定长编码 它们采用同样数目的二进制位表示消息中的一个字符 与之相对应的是变长编码 即用可变的二进制位数表示不同的字符 一般而言 如果在我们的消息中 某写符号出现得比较频繁 而另一些比较少见 那么就可以通过为这些出现比较频繁的字符指定比较短的二进制位编码来达到节省空间的目的 但是采用二

Huffman 编码树

像SCAII这样即那个每个字符表示为一个7为二进制的序列的编码方式称为定长编码,它们采用同样数目的二进制位表示消息中的一个字符.与之相对应的是变长编码,即用可变的二进制位数表示不同的字符.

一般而言,如果在我们的消息中,某写符号出现得比较频繁,而另一些比较少见,那么就可以通过为这些出现比较频繁的字符指定比较短的二进制位编码来达到节省空间的目的.

但是采用二进制编码有一个困难,它需要在读二进制序列是判断合适到达了一个字符的结束.解决这一问题的方法可以在每个字母后面用一个特殊分隔符(莫尔编码). 另一种解决方式是设计编码方式,是得其中每个字符的完整编码都不是另一个字符编码的开始一段.这中编码方式称为前缀编码.一般而言能够通过变长前缀码去利用编码消息中符号出现的相对频度,就能节省空间.完成这一特定时间的方式称为Huffman编码.一个Huffman编码可以表示为一个二叉树,其中的树叶是被编码的符号.树中的每个每个非叶子节点代表一个集合,其中包含饿这一节点之下的所有书上的符号.每个位于书上的符号被赋予一个权重,也就是它的相对频度.非叶子节点所包含的权重位是位于它之下的所有叶子节点的权重之和.这种权重在编码和解码中国并不使用.

下图是一颗Huffman编码树

Huffman 编码树



在用Huffman树做一个序列解码时,我们从树根开始,通过位序列中的0或者1确定是向左移动还是向右移动.每当达到一个叶子节点时就生成出一个符号,然后再从新从树根开始去确定下一个符号,直到解码完给定的的二进制序列为止.

列如,如果有一个序列 .从数根开始,序列的第一位是1, 所以我们向右分支移动,第二位是0,所以我们向左移动,第三位是0 ,所以向左移动.这是已经到达Bde叶,所以被解码消息中的第一个符号是B.接着再从树根开始重复上述过程,最后可以确定整个消息是BAC.



生成Huffman树

给定了符号的 符号表和它们的相对频度,怎么才能构造出最好的编码?(也就是怎样的树能是消息编码的位数最少).Huffman给出了完成这一事件的一个算法,并且证明给了对于符号所出现的相对频度与构造树的消息符号的消息而言,这样产生的编码是最好的边长编码.

生成Huffman树的算法非常简单,就是安排这棵树,使得那些带有最低平度的符号出现在离树根最远的地方.这一构造过程从叶节点的集合开始,这种节点中包含包含各个符号和他们出现的频度,这就是开始构造编码数的初始数据.现在要找出连个具有最低权重的叶,并归并它们,产生出一个以这两个节点为左右分支的节点.新节点的权重就是这两个叶节点的权重之和.然后继续重复这一过程当集合只剩下一个节点时停止,而这个节点就是根节点.



Huffman 编码树

这一算法不总能描述一棵唯一的树,这是因为每步选择出的最小权重节点可能不唯一,在左归并是,两个节点的顺序也是任意的,也就是说,随便哪个都可以作为左分支,或者右分支.

=====================================================

代码来自维基百科

//以下為C++程式碼,在GCC下編譯通過 //僅用於示範如何根據權值構建霍夫曼樹, //沒有經過性能上的優化及加上完善的異常處理。 #include <cstdlib> #include <iostream> #include <deque> #include <algorithm> using namespace std; const int size=10; struct node //霍夫曼樹節點結構 { unsigned key; //保存權值 node* lchild; //左孩子指針 node* rchild; //右孩子指針 }; deque<node*> forest; deque<bool> code; //此處也可使用bitset node* ptr; int frequency[size]={0}; void printCode(deque<bool> ptr); //用於輸出霍夫曼編碼 bool compare( node* a, node* b) { return a->key < b->key; } int main(int argc, char *argv[]) { for(int i=0;i<size;i++) { cin>>frequency[i]; //輸入10個權值 ptr=new node; ptr->key=frequency[i]; ptr->lchild=NULL; ptr->rchild=NULL; forest.push_back(ptr); }//形成森林,森林中的每一棵樹都是一個節點 //從森林構建霍夫曼樹 for(int i=0;i<size-1;i++) { sort(forest.begin(),forest.end(),compare); ptr=new node; //以下代碼使用下標索引隊列元素,具有潛在危險,使用時請注意 ptr->key=forest[0]->key+forest[1]->key; ptr->lchild=forest[0]; ptr->rchild=forest[1]; forest.pop_front(); forest.pop_front(); forest.push_back(ptr); } ptr=forest.front();//ptr是一個指向根的指針 system("PAUSE"); return EXIT_SUCCESS; } void printCode(deque<bool> ptr) { //deque<bool> for (int i=0;i<ptr.size();i++) { if(ptr[i]) cout<<"1"; else cout<<"0"; } }





维基百科连接:http://zh.wikipedia.org/wiki/霍夫曼编码



版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/232687.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 使用 Java DB (Derby) 数据库

    使用 Java DB (Derby) 数据库使用JavaDB(Derby)数据库https://netbeans.org/kb/docs/ide/java-db_zh_CN.html本文档说明了如何在NetBeansIDE中设置与JavaDB数据库的连接。在建立连接之后,即可开始在IDE中使用该数据库,您可以执行的操作包括创建表、用数据填充表、运行SQL语句和查询等。…

    2022年7月8日
    23
  • Redis Sentinel实现的机制与原理详解

    Redis Sentinel实现的机制与原理详解

    2022年3月2日
    36
  • booth算法原理的简单化理解「建议收藏」

    booth算法原理的简单化理解「建议收藏」最近,在学习带符号二进制数乘法(multiplicationof signednumbers)时接触到了布思算法(boothalgorithm)。由于是第一次接触,对于其原理却一无所知,书上的解释以及网上的文章不知是自己才疏学浅还本来就是泛泛而谈,没有让我了解其本质。经过长时间的思考分析,最终找到了一种比较简单的理解方法。举一个简单的例子,比如说计算10100001×00111110,

    2025年8月14日
    1
  • PHP获取客户端IP地址方式[通俗易懂]

    PHP获取客户端IP地址方式[通俗易懂]一、如果没有使用代理服务器REMOTE_ADDR=客户端IPHTTP_X_FORWARDED_FOR=没数值或不显示$ip=$_SERVER[‘REMOTE_ADDR’];二、使用透明代理REMOTE_ADDR=最后一个代理服务器IPHTTP_X_FORWARDED_FOR=客户端真实IP(经过多个代理服务器时,这个值类似:221.5.252….

    2025年7月21日
    4
  • vr体验心得_在我们新的VR学习体验中逃脱女巫的小屋

    vr体验心得_在我们新的VR学习体验中逃脱女巫的小屋vr体验心得OurbrandnewprojectforUnityLearnisanimmersiveVRescaperoom.ExplorethepotentialofVRinUnityandcreateyourownexperienceinasimpleprototypeenvironment.Letusintroduceyou…

    2022年10月1日
    3
  • c中getline的用法_enum用法

    c中getline的用法_enum用法getline()用法getline是C++标准库函数;它有两种形式,一种是头文件<istream>中输入流成员函数;一种在头文件<string>中普通函数;它遇到以下情况发生会导致生成的本字符串结束:(1)到文件结束,(2)遇到函数的定界符,(3)输入达到最大限度。输入流成员函数getline()函数语法结构:在<istream>中的g…

    2025年7月20日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号