哈夫曼树又称最优二叉树,是一种带权路径长度最短的二叉树。所谓树的带权路径长度,就是树中所有的叶结点的权值乘上其到根结点的路径长度(若根结点为0层,叶结点到根结点的路径长度为叶结点的层数)。树的带权路径长度记为WPL=(W1*L1+W2*L2+W3*L3+...+Wn*Ln),N个权值Wi(i=1,2,...n)构成一棵有N个叶结点的二叉树,相应的叶结点的路径长度为Li(i=1,2,...n)。可以证明哈夫曼树的WPL是最小的。

什么是哈夫曼树呢?

样例解释

哈夫曼树是一种带权路径长度最短的二叉树,也称为最优二叉树。下面用一幅图来说明。

它们的带权路径长度分别为:

图a: WPL=5*2+7*2+2*2+13*2=54

图b: WPL=5*3+2*3+7*2+13*1=48

设 根节点深度为 0

WPL

理解就是各个点的编码值和在哈夫曼生成树上的深度的乘积的和

可见,图b的带权路径长度较小,我们可以证明图b就是哈夫曼树(也称为最优二叉树)。

构建哈夫曼树 —————— 选集合中最小的两个(every)

假设有n个权值,则构造出的哈夫曼树有n个叶子结点。 n个权值分别设为 w1、w2、…、wn,则哈夫曼树的构造规则为:

  1. 将w1、w2、…,wn看成是有n 棵树的森林(每棵树仅有一个结点);
  2. 在森林中选出两个根结点的权值最小的树合并,作为一棵新树的左、右子树,且新树的根结点权值为其左、右子树根结点权值之和;
  3. 从森林中删除选取的两棵树,并将新树加入森林;
  4. 重复(2)、(3)步,直到森林中只剩一棵树为止,该树即为所求得的哈夫曼树。

三,哈夫曼编码

利用哈夫曼树求得的用于通信的二进制编码称为哈夫曼编码。树中从根到每个叶子节点都有一条路径,对路径上的各分支约定指向左子树的分支表示”0”码,指向右子树的分支表示“1”码,取每条路径上的“0”或“1”的序列作为各个叶子节点对应的字符编码,即是哈夫曼编码。

就拿上图例子来说:

A,B,C,D对应的哈夫曼编码分别为:111,10,110,0

用图说明如下:

记住,设计电文总长最短的二进制前缀编码,就是以n个字符出现的频率作为权构造一棵哈夫曼树,由哈夫曼树求得的编码就是哈夫曼编码

对N(≥)个权值均不相同的字符构造哈夫曼树,则树中任一非叶结点的权值一定不小于下一层任一结点的权值。

正确:

哈夫曼树的构造特点,为了使得WPL值最小,那么越是值大的节点,他在哈夫曼生成树上的深度越小

可以根据上述公式证明

,假设WPL值是个定值,增加val(i),要保持WPL的值不改变,那么deep(i)必须相应的减少。

对N(N≥2)个权值均不相同的字符构造哈夫曼树。下列关于该哈夫曼树的叙述中,错误的是:

1. 先去理解哈夫曼树的构造过程,优先队列,每次取两个val最小的点,进行组合,所以,Huffman树中不会存在度数为0的点

2.同理,下面会给出代码;

3.1-1已经证明

4.错误

n 个数值,进行编码,求解WPL值的代码,stl 优先队列实现

代码很重要,最好记下来

#include<bits/stdc++.h>
#define LL long long
#define exp 1e-9
#define MAXN 1000010
using namespace std;  int main( )
{
//  freopen("D:\\in.txt","r",stdin);  int n,i;  LL sum,tmp,q1,q2;  scanf("%d",&n);
//构建小顶堆priority_queue<LL,vector<LL>,greater<LL> > pq;  for(i=1;i<=n;i++)  {  scanf("%lld",&tmp);  pq.push(tmp);  }  sum=0;  if(n==1)  {  printf("%lld\n",tmp);  }  else  {  while(!pq.empty())  {  q1=pq.top();  pq.pop();  if(pq.empty())  {  printf("%lld\n",sum);  break;  }  else  {  q2=pq.top();  pq.pop();  tmp=q1+q2;  pq.push(tmp);  sum+=tmp;  }  }  }  return 0;
}    

2-5

已知字符集{ a, b, c, d, e, f, g, h }。若各字符的哈夫曼编码依次是 0100, 10, 0000, 0101, 001, 011, 11, 0001,则编码序列 0100011001001011110101 的译码结果是:

这种题目:枚举暴力尝试:

C语言实现Huffman , 便于理解编码过程,做题推荐上面的代码,不推荐记忆;

#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;
}

参考:

https://cloud.tencent.com/developer/article/1009606

https://baike.baidu.com/item/%E5%93%88%E5%A4%AB%E6%9B%BC%E6%A0%91

Huffman树(哈夫曼树)相关推荐

  1. Huffman Tree哈夫曼树权值路径长度WPL计算,binarytree ,Python

    Huffman Tree哈夫曼树(霍夫曼树.赫夫曼树)权值路径长度WPL计算,binarytree ,Python 计算定义:把构建成功的哈夫曼树的每一个边缘节点(叶子)值乘以该节点到根的路径长度,最 ...

  2. 数据结构与算法之Huffman tree(赫夫曼树 / 霍夫曼树 / 哈夫曼树 / 最优二叉树)

    目录 赫夫曼树概述 定义 构造赫夫曼树步骤 代码实现 赫夫曼树概述 HuffmanTree因为翻译不同所以有其他的名字:赫夫曼树.霍夫曼树.哈夫曼树 赫夫曼树又称最优二叉树,是一种带权路径长度最短的二 ...

  3. 哈夫曼树(带权路径长度+树的带权路径长度+哈夫曼树定义+构造哈夫曼树+哈夫曼树性质+哈夫曼编码+计算平均码长-这里指WPL)

    带权路径长度 树的带权路径长度WPL 哈夫曼树 哈夫曼树构造 哈夫曼树性质 哈夫曼编码 固定长度编码 可变长编码 前缀编码 固定长度编码.可变长编码.前缀编码.哈夫曼编码 思维倒图 试题

  4. Huffman Coding 哈夫曼树

    一.实验名称:Huffman Coding 二.实验目的: 熟练掌握哈夫曼树的数据结构,结构的特点: 能够实现哈夫曼树的基本操作:如构造,插入等 利用最小堆降低哈夫曼树的时间复杂度. 熟练掌握最小堆的 ...

  5. Huffman Tree哈夫曼树的最小堆实现

    带权路径长度WPL:从根结点到各个叶子结点的路径长度和相应叶子结点权值的乘积之和 哈夫曼树:带权路径长度最小的二叉树(最优二叉树) -没有度为1的结点,有n个叶子结点的哈夫曼树共有2n-1个结点 -任 ...

  6. UVA_12676_Inverting Huffman(哈夫曼树)

    题目链接:http://uva.onlinejudge.org/external/126/12676.pdf 题型:数据结构 题意: 话说这题目可真长,读了两三遍不知道啥意思... 关于字符串转换为哈 ...

  7. 快速画出哈夫曼树/霍夫曼树/最优树

    2019独角兽企业重金招聘Python工程师标准>>> 哈夫曼树(霍夫曼树)又称为最优二叉树. n个叶子结点的哈夫曼树共有几个结点 ? Huffman 树是所谓的正则二叉树,只有度为 ...

  8. PTA 线性结构/AVL树/哈夫曼树错题

    1.稀疏矩阵压缩存储后,必会失去随机存取功能. T F 解析:稀疏矩阵的存储方式是将数据压缩存储进一维数组,数组下标与之前的不相同了,想要某一元素需要根据公式计算它的下标,所以说是失去了随机存取的功能 ...

  9. 数据结构-树(哈夫曼树)

    树的基本概念 定义 树(Tree)是n(n>=0)个结点的有限集.n=0时成为空树. 在任意一个非空树中:有且仅有一个特定的称为根(Root)的结点:n>1时,其余结点可分为m(m> ...

  10. java哈夫曼_用 JAVA 实现哈夫曼树(Huffman Tree)

    -1. 什么是树 树是一种 有层次关系的 数据结构.它由结点组成. 图一: 树的结点由 数据域 和 子结点域 组成.数据域 作为数据的容器:子结点域 存放 子结点 的地址.一个结点是它的子结点的父结点 ...

最新文章

  1. 使用axios post 提交数据,后台获取不到提交的数据解决方案
  2. 以女朋友为例讲解 TCP/IP 三次握手与四次挥手
  3. 使用 xCAT 简化 AIX 集群的部署和管理
  4. SimGAN-Captcha代码阅读与复现
  5. TweetLouder.com:在微博上找你喜好的乐队
  6. 使用virt-install安装kvm虚拟机时需要的问题
  7. 软考初级程序员主要考什么?如何复习?
  8. EPS绘图常用快捷键及复杂台阶的画法
  9. ColorZilla|网页颜色颜色提取
  10. 大一微积分笔记整理_大一高等数学学习方法
  11. php文件断点上传文件,php大文件上传支持断点上传
  12. Java毕业设计 JSP+MySQL幼儿园信息管理系统
  13. Linux磁盘空间爆满怎么办?定时文件清理脚本配置实现
  14. 仅逗oier们一笑(不定期更新中)
  15. thinkpad重装系统不引导_联想Y400电脑装WIN7无法重装系统的解决方法
  16. 三点钟社群联合发起人Sky: 中国版“马克·扎克伯格”,用区块链激励差异化价值创造者...
  17. Vue乱搞系列之axios发起表单请求
  18. 微信小程序 细分_如何将细分网络模型与iPhone应用程序集成
  19. Android Jetpack Compose 播放器动画
  20. 推荐系统深度学习实战之Wide_Deep

热门文章

  1. vertica java_Vertica数据查询优化
  2. 从零到一学习计算机视觉:朋友圈爆款背后的计算机视觉技术与应用 | 公开课笔记...
  3. express+socket.io 共享session
  4. 由海天瑞声支持,全球最大多领域英语开源数据集发布
  5. 搭配emuc-b202 can卡通讯时,时断时续
  6. 产品界的三大定律 --周宏桥
  7. idea2018破解有效期至2100年
  8. 【剑指 Offe】11. 旋转数组的最小数字
  9. JAVA基础+集合+多线程+JVM
  10. 云端体验鸿蒙,AI加持的另类彩电之华为智慧屏带你体验鸿蒙