博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
哈夫曼树与哈夫曼编码
阅读量:7015 次
发布时间:2019-06-28

本文共 2191 字,大约阅读时间需要 7 分钟。

在一般的数据结构的书中,树的那章后面,著者一般都会介绍一下哈夫曼(HUFFMAN) 树和哈夫曼编码。哈夫曼编码是哈夫曼树的一个应用。哈夫曼编码应用广泛,如 JPEG中就应用了哈夫曼编码。 首先介绍什么是哈夫曼树。哈夫曼树又称最优二叉树, 是一种带权路径长度最短的二叉树。所谓树的带权路径长度,就是树中所有的叶结点 的权值乘上其到根结点的 路径长度(若根结点为0层,叶结点到根结点的路径长度 为叶结点的层数)。树的带权路径长度记为WPL= (W1*L1+W2*L2+W3*L3+...+Wn*Ln) ,N个权值Wi(i=1,2,...n)构成一棵有N个叶结点的二叉树,相应的叶结点的路径 长度为Li(i=1,2,...n)。可以证明哈夫曼树的WPL是最小的。

哈夫曼编码步骤:

一、对给定的n个权值{W1,W2,W3,...,Wi,...,Wn}构成n棵二叉树的初始集合F= {T1,T2,T3,...,Ti,...,Tn},其中每棵二叉树Ti中只有一个权值为Wi的根结点,它的左右子树均为空。(为方便在计算机上实现算 法,一般还要求以Ti的权值Wi的升序排列。)

二、在F中选取两棵根结点权值最小的树作为新构造的二叉树的左右子树,新二叉树的根结点的权值为其左右子树的根结点的权值之和。
三、从F中删除这两棵树,并把这棵新的二叉树同样以升序排列加入到集合F中。
四、重复二和三两步,直到集合F中只有一棵二叉树为止。

简易的理解就是,假如我有A,B,C,D,E五个字符,出现的频率(即权值)分别为5,4,3,2,1,那么我们第一步先取两个最小权值作为左右子树构造一个新树,即取1,2构成新树,其结点为1+2=3,如图:

虚线为新生成的结点,第二步再把新生成的权值为3的结点放到剩下的集合中,所以集合变成{5,4,3,3},再根据第二步,取最小的两个权值构成新树,如图:

再依次建立哈夫曼树,如下图:

其中各个权值替换对应的字符即为下图:

所以各字符对应的编码为:A->11,B->10,C->00,D->011,E->010

霍夫曼编码是一种无前缀编码。解码时不会混淆。其主要应用在数据压缩,加密解密等场合。

C语言代码实现:

 
/*------------------------------------------------------------------------- * Name:   哈夫曼编码源代码。 * Date:   2011.04.16 * Author: Jeffrey Hill+Jezze(解码部分) * 在 Win-TC 下测试通过 * 实现过程:着先通过 HuffmanTree() 函数构造哈夫曼树,然后在主函数 main()中 *           自底向上开始(也就是从数组序号为零的结点开始)向上层层判断,若在 *           父结点左侧,则置码为 0,若在右侧,则置码为 1。最后输出生成的编码。 *------------------------------------------------------------------------*/#include 
#include
#define MAXBIT 100#define MAXVALUE 10000#define MAXLEAF 30#define MAXNODE MAXLEAF*2 -1 typedef struct { int bit[MAXBIT]; int start;} HCodeType; /* 编码结构体 */typedef struct{ int weight; int parent; int lchild; int rchild; int 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=i; //实际值,可根据情况替换为字母 } /* end for */ /* 输入 n 个叶子结点的权值 */ for (i=0; i

转载于:https://www.cnblogs.com/hdk1993/p/4931421.html

你可能感兴趣的文章
Ruby Code Style
查看>>
Redis快速入门:初识Redis
查看>>
Pdlrt.exe 文件出错
查看>>
2016-11-12试题解题报告
查看>>
node web 应用热更新
查看>>
汇编实验五
查看>>
机器学习中矩阵的求导知识
查看>>
JAVA debug 调试demo
查看>>
洛谷P2336 [SCOI2012]喵星球上的点名(后缀数组+莫队)
查看>>
Node.js 搭建HTTP服务器,提供文件下载
查看>>
设计模式学习笔记之模板方法模式
查看>>
Web Service
查看>>
express 3.5 Err: request aborted
查看>>
css推荐
查看>>
点沙成金:半导体芯片(转载)
查看>>
如何进行有效沟通避免出现误会
查看>>
UbuntuFAQ
查看>>
一致性hash与CRUSH算法总结
查看>>
关于pandas精度控制
查看>>
HDU-1069-Monkey and Banana
查看>>