1. <span style="font-size:18px;">/*
  2.  
  3. 1.在一棵二叉树中,我们定义从A节点到B节点所经过的分支序列为从A节点到B节点的路径;
  4. 定义从A节点到B节点所经过的分支个数为从A节点到B节点的路径长度。
  5. 定义从二叉树的根节点到二叉树中全部叶节点的路径长度之和为该二叉树的路径长度。
  6. 2.假设二叉树中的叶节点都带有权值,则能够把这个定义推广。设二叉树有n歌带权值的叶节点,定义从二叉树的
  7. 根节点到二叉树中全部叶节点的路径长度与相应叶节点权值的乘积之和为该二叉树的带权路径长度。
  8. WPL=(wi*li)(i从1到n)
  9. 3.我们把具有最小带权路径长度的二叉树称作哈夫曼树或最优二叉树
  10. 4.哈夫曼树构造算法:
  11. (1):由给定的n个权值{w1,w2,w3,...,wn}构造n棵仅仅有根节点的二叉树,从而得到一个二叉树森林F={T1,T2,T3,....,TN}。
  12. (2):在二叉树森林F中选取根节点的权值最小和次小的两棵二叉树作为新的二叉树的左右子树构造新的二叉树,
  13. 新的二叉手的根节点权值为左右子树根节点权值之和。
  14. (3):从二叉树森林F中删除作为新二叉树左右子树的两棵二叉树,将新二叉树增加到二叉树森林F中。
  15. (4):反复步骤(2)(3)。当二叉树森林F中仅仅剩下一颗二叉树时。这棵二叉树就是所构造的哈夫曼树
  16.  
  17. 5.哈夫曼树能够用于解决最优化问题。比如电文的编码问题
  18. */
  19.  
  20. #include<stdio.h>
  21. #include<malloc.h>
  22. #include<stdlib.h>
  23. #define MaxN 10//初始设定的最大结点个数
  24. #define MaxValue 10000//初始设定的权值最大值
  25. #define MaxBit 4//初始设定的最大编码位数
  26. typedef struct{
  27.  
  28. int weight;//权值
  29. int flag;//标记,是否已经增加到哈夫曼树中
  30. int parent;//双亲节点下标
  31. int leftChild;//左孩子下标
  32. int rightChile;//右孩子下标
  33. }HaffNode;//哈夫曼树的结点构体
  34.  
  35. typedef struct{
  36.  
  37. int bit[MaxN];//数组
  38. int start;//编码的起始下标
  39. int weight;//字符的权值
  40. }Code;//哈夫曼编码的结构
  41.  
  42. //建立哈夫曼树
  43. void Haffman(int weight[],int n,HaffNode haffTree[]){
  44. //建立叶结点个数为n,权值数组为weight的哈夫曼树haffTree
  45. int i,j,m1,m2,x1,x2;
  46. //哈夫曼树的haffTree的初始化,n个叶节点的二叉树共同拥有2n-1个结点
  47. for(i=0;i<2*n-1;i++){
  48.  
  49. if(i<n){
  50.  
  51. haffTree[i].weight=weight[i];
  52. }else{
  53.  
  54. haffTree[i].weight=0;
  55. }
  56.  
  57. haffTree[i].parent=-1;
  58. haffTree[i].flag=0;
  59. haffTree[i].leftChild=-1;
  60. haffTree[i].rightChile=-1;
  61.  
  62. }
  63.  
  64. //构造哈夫曼树haffTree的n-1个非叶节点
  65. for(i=0;i<n-1;i++){
  66.  
  67. m1=m2=MaxValue;
  68. x1=x2;
  69. for(j=0;j<n+i;j++){//找出权值最小和次小的子树
  70. if(haffTree[j].weight<m1&&haffTree[j].flag==0){
  71. //x1最小的下标,x2次小的下标,m1最小的权值,m2次小的权值
  72. //flag==0表示还没有增加到哈夫曼树
  73. m2=m1;
  74. x2=x1;
  75. m1=haffTree[j].weight;
  76. x1=j;
  77. }else if(haffTree[j].weight<m2&&haffTree[j].flag==0){
  78.  
  79. m2=haffTree[j].weight;
  80. x2=j;
  81. }
  82. }
  83. //将找出的两棵权值最小和次小的子树合并为一棵
  84. haffTree[x1].parent=n+i;
  85. haffTree[x2].parent=n+i;
  86. haffTree[x1].flag=1;
  87. haffTree[x2].flag=1;
  88. haffTree[n+i].weight=haffTree[x1].weight+haffTree[x2].weight;
  89. haffTree[n+i].leftChild=x1;
  90. haffTree[n+i].rightChile=x2;
  91. }
  92. }
  93.  
  94. void HaffmanCode(HaffNode haffTree[],int n,Code haffCode[]){
  95.  
  96. //由n个结点的哈夫曼树haffTree构造哈夫曼编码haffCode
  97. Code *cd=(Code *)malloc(sizeof(Code));
  98. int i,j,child,parent;
  99. //求n个叶结点的哈夫曼编码
  100. for(i=0;i<n;i++){
  101. cd->start=n-1;//不等长编码的最后一位为n-1
  102. cd->weight=haffTree[i].weight;//取得编码相应的权值
  103. child=i;
  104. parent=haffTree[child].parent;
  105. //由叶节点向上直到根结点
  106. while(parent!=-1){
  107. if(haffTree[parent].leftChild==child){
  108.  
  109. cd->bit[cd->start]=0;//左孩子分支编码0
  110. }else{
  111.  
  112. cd->bit[cd->start]=1;//右孩子分支编码1
  113. }
  114. cd->start--;
  115. child=parent;
  116. parent=haffTree[child].parent;
  117. }
  118. for(j=cd->start+1;j<n;j++){
  119.  
  120. haffCode[i].bit[j]=cd->bit[j];//保存每一个叶节点的编码
  121. }
  122. haffCode[i].start=cd->start+1;//保存叶结点编码的起始位
  123. haffCode[i].weight=cd->weight;//保存编码相应的权值
  124. }
  125. }
  126.  
  127. void main(){
  128.  
  129. int i,j,n=4;
  130. int weight[]={1,3,5,7};
  131. HaffNode *myHaffTree=(HaffNode *)malloc(sizeof(HaffNode)*(2*n-1));
  132. Code *myHaffCode=(Code *)malloc(sizeof(Code)*n);
  133. if(n>MaxN){
  134.  
  135. printf("给出的n越界。改动MaxN!!!\n");
  136. exit(1);
  137. }
  138.  
  139. Haffman(weight,n,myHaffTree);
  140. HaffmanCode(myHaffTree,n,myHaffCode);
  141. //输出每一个叶节点的哈夫曼编码
  142. for(i=0;i<n;i++){
  143.  
  144. printf("Weight=%d Code=",myHaffCode[i].weight);
  145. for(j=myHaffCode[i].start;j<n;j++){
  146.  
  147. printf("%d",myHaffCode[i].bit[j]);
  148. }
  149. printf("\n");
  150. }
  151.  
  152. }

haffman哈夫曼编码的实现的更多相关文章

  1. 哈夫曼(huffman)树和哈夫曼编码

    哈夫曼树 哈夫曼树也叫最优二叉树(哈夫曼树) 问题:什么是哈夫曼树? 例:将学生的百分制成绩转换为五分制成绩:≥90 分: A,80-89分: B,70-79分: C,60-69分: D,<60 ...

  2. java 哈夫曼编码

    //哈夫曼树类 public class HaffmanTree { //最大权值 ; int nodeNum ; //叶子结点个数 public HaffmanTree(int n) { this. ...

  3. c++实验8 哈夫曼编码-译码器

    哈夫曼编码-译码器 此次实验的注释解析多加不少---若对小伙伴们有帮助 希望各位麻烦点个关注 多谢 1.哈夫曼树构造算法为: (1)由给定的n个权值{w1,w2,…,wn}构造n棵只有根结点的二叉树, ...

  4. (转载)哈夫曼编码(Huffman)

    转载自:click here 1.哈夫曼编码的起源: 哈夫曼编码是 1952 年由 David A. Huffman 提出的一种无损数据压缩的编码算法.哈夫曼编码先统计出每种字母在字符串里出现的频率, ...

  5. 数据结构图文解析之:哈夫曼树与哈夫曼编码详解及C++模板实现

    0. 数据结构图文解析系列 数据结构系列文章 数据结构图文解析之:数组.单链表.双链表介绍及C++模板实现 数据结构图文解析之:栈的简介及C++模板实现 数据结构图文解析之:队列详解与C++模板实现 ...

  6. HDU2527 哈夫曼编码

    Safe Or Unsafe Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

  7. *HDU1053 哈夫曼编码

    Entropy Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Sub ...

  8. YTU 3027: 哈夫曼编码

    原文链接:https://www.dreamwings.cn/ytu3027/2899.html 3027: 哈夫曼编码 时间限制: 1 Sec  内存限制: 128 MB 提交: 2  解决: 2 ...

  9. 使用F#来实现哈夫曼编码吧

    最近算法课要求实现哈夫曼编码,由于前面的问题都是使用了F#来解决,偶然换成C#也十分古怪,报告也不好看,风格差太多.一开始是打算把C#版本的哈夫曼编码换用F#来写,结果写到一半就觉得日了狗了...毕竟 ...

随机推荐

  1. python2 UnicodeDecodeError: 'ascii' codec can't decode byte 0xce in position 7: ordinal not in range(128)

    python在安装时,默认的编码是ascii,当程序中出现非ascii编码时,python的处理常常会报这样的错UnicodeDecodeError: 'ascii' codec can't deco ...

  2. Ajax实现异步刷新验证用户名是否已存在

    由于要做一个注册页面,看到许多网站上都是使用Ajax异步刷新验证用户名是否可用的,所以自己也动手做一个小实例 都是简单的实例,所以直接发代码 静态页面Ajax.html <html> &l ...

  3. ucos-III基础教程汇总

    目录: 1.ucos-III前言 2.uC/OS-III 概要 3.移植 uC/OS-III 到 STM32 4.调度器 5.uC/OS-III 时钟节拍,时间管理,时间片调度

  4. Java中数据库连接池原理机制的详细讲解

    连接池的基本工作原理 1.基本概念及原理 由上面的分析可以看出,问题的根源就在于对数据库连接资源的低效管理.我们知道,对于共享资源,有一个很著名的设计模式:资源池(Resource Pool).该模式 ...

  5. 一款纯css3实现的鼠标经过按钮特效

    今天再给大家带来一款纯css3实现的鼠标经过按钮特效.这款按钮非常简单,但效果很好,非常漂亮.一起看下效果图: 在线预览   源码下载 实现的代码. html代码: <div align=&qu ...

  6. 【C#/WPF】如何查看System.Windows.Interactivity.dll中EventTrigger的EventNames属性有哪些

    WPF项目中,从Nuget搜索并下载System.Windows.Interactivity.dll,安装到项目中,并在XAML界面引入. <UserControl xmlns:i=" ...

  7. Android——电脑蓝屏重启后,studio无法认出Android环境 setup JDK(缓存!缓存!缓存)

    电脑蓝屏重启后,studio无法认出Android环境 setup JDK 问题重现:因为工作问题,需要用到模拟器,然后创建了模拟器后开启了漫长的等待之旅,两三分钟之后win8蓝屏,重启,再次打开,依 ...

  8. 有趣的 Mysql 存储引擎

    Mysql 提供了一套统一的应用开发模型和核心 API,因此,尽管不同的存储引擎拥有不同的特性,不过对于开发人员,应用操作都是完全透明的.应用层的连接并不直接访问存储引擎层,而是访问 Mysql 提供 ...

  9. android之存储篇_SQLite数据库入门

    SQLite最大的特点是你可以把各种类型的数据保存到任何字段中,而不用关心字段声明的数据类型是什么. 例如:可以在Integer类型的字段中存放字符串,或者在布尔型字段中存放浮点数,或者在字符型字段中 ...

  10. Qt::WA_DeleteOnClose 造成的野指针问题

    今天遇到了一个由Qt::WA_DeleteOnClose造成的野指针问题,在网上搜到的一个求助贴如下(http://bbs.csdn.net/topics/380182058): 主窗口类QMainW ...