haffman哈夫曼编码的实现
<span style="font-size:18px;">/* 1.在一棵二叉树中,我们定义从A节点到B节点所经过的分支序列为从A节点到B节点的路径;
定义从A节点到B节点所经过的分支个数为从A节点到B节点的路径长度。
定义从二叉树的根节点到二叉树中全部叶节点的路径长度之和为该二叉树的路径长度。
2.假设二叉树中的叶节点都带有权值,则能够把这个定义推广。设二叉树有n歌带权值的叶节点,定义从二叉树的
根节点到二叉树中全部叶节点的路径长度与相应叶节点权值的乘积之和为该二叉树的带权路径长度。
WPL=(wi*li)(i从1到n)
3.我们把具有最小带权路径长度的二叉树称作哈夫曼树或最优二叉树
4.哈夫曼树构造算法:
(1):由给定的n个权值{w1,w2,w3,...,wn}构造n棵仅仅有根节点的二叉树,从而得到一个二叉树森林F={T1,T2,T3,....,TN}。
(2):在二叉树森林F中选取根节点的权值最小和次小的两棵二叉树作为新的二叉树的左右子树构造新的二叉树,
新的二叉手的根节点权值为左右子树根节点权值之和。
(3):从二叉树森林F中删除作为新二叉树左右子树的两棵二叉树,将新二叉树增加到二叉树森林F中。
(4):反复步骤(2)(3)。当二叉树森林F中仅仅剩下一颗二叉树时。这棵二叉树就是所构造的哈夫曼树 5.哈夫曼树能够用于解决最优化问题。比如电文的编码问题
*/ #include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
#define MaxN 10//初始设定的最大结点个数
#define MaxValue 10000//初始设定的权值最大值
#define MaxBit 4//初始设定的最大编码位数
typedef struct{ int weight;//权值
int flag;//标记,是否已经增加到哈夫曼树中
int parent;//双亲节点下标
int leftChild;//左孩子下标
int rightChile;//右孩子下标
}HaffNode;//哈夫曼树的结点构体 typedef struct{ int bit[MaxN];//数组
int start;//编码的起始下标
int weight;//字符的权值
}Code;//哈夫曼编码的结构 //建立哈夫曼树
void Haffman(int weight[],int n,HaffNode haffTree[]){
//建立叶结点个数为n,权值数组为weight的哈夫曼树haffTree
int i,j,m1,m2,x1,x2;
//哈夫曼树的haffTree的初始化,n个叶节点的二叉树共同拥有2n-1个结点
for(i=0;i<2*n-1;i++){ if(i<n){ haffTree[i].weight=weight[i];
}else{ haffTree[i].weight=0;
} haffTree[i].parent=-1;
haffTree[i].flag=0;
haffTree[i].leftChild=-1;
haffTree[i].rightChile=-1; } //构造哈夫曼树haffTree的n-1个非叶节点
for(i=0;i<n-1;i++){ m1=m2=MaxValue;
x1=x2;
for(j=0;j<n+i;j++){//找出权值最小和次小的子树
if(haffTree[j].weight<m1&&haffTree[j].flag==0){
//x1最小的下标,x2次小的下标,m1最小的权值,m2次小的权值
//flag==0表示还没有增加到哈夫曼树
m2=m1;
x2=x1;
m1=haffTree[j].weight;
x1=j;
}else if(haffTree[j].weight<m2&&haffTree[j].flag==0){ m2=haffTree[j].weight;
x2=j;
}
}
//将找出的两棵权值最小和次小的子树合并为一棵
haffTree[x1].parent=n+i;
haffTree[x2].parent=n+i;
haffTree[x1].flag=1;
haffTree[x2].flag=1;
haffTree[n+i].weight=haffTree[x1].weight+haffTree[x2].weight;
haffTree[n+i].leftChild=x1;
haffTree[n+i].rightChile=x2;
}
} void HaffmanCode(HaffNode haffTree[],int n,Code haffCode[]){ //由n个结点的哈夫曼树haffTree构造哈夫曼编码haffCode
Code *cd=(Code *)malloc(sizeof(Code));
int i,j,child,parent;
//求n个叶结点的哈夫曼编码
for(i=0;i<n;i++){
cd->start=n-1;//不等长编码的最后一位为n-1
cd->weight=haffTree[i].weight;//取得编码相应的权值
child=i;
parent=haffTree[child].parent;
//由叶节点向上直到根结点
while(parent!=-1){
if(haffTree[parent].leftChild==child){ cd->bit[cd->start]=0;//左孩子分支编码0
}else{ cd->bit[cd->start]=1;//右孩子分支编码1
}
cd->start--;
child=parent;
parent=haffTree[child].parent;
}
for(j=cd->start+1;j<n;j++){ haffCode[i].bit[j]=cd->bit[j];//保存每一个叶节点的编码
}
haffCode[i].start=cd->start+1;//保存叶结点编码的起始位
haffCode[i].weight=cd->weight;//保存编码相应的权值
}
} void main(){ int i,j,n=4;
int weight[]={1,3,5,7};
HaffNode *myHaffTree=(HaffNode *)malloc(sizeof(HaffNode)*(2*n-1));
Code *myHaffCode=(Code *)malloc(sizeof(Code)*n);
if(n>MaxN){ printf("给出的n越界。改动MaxN!!!\n");
exit(1);
} Haffman(weight,n,myHaffTree);
HaffmanCode(myHaffTree,n,myHaffCode);
//输出每一个叶节点的哈夫曼编码
for(i=0;i<n;i++){ printf("Weight=%d Code=",myHaffCode[i].weight);
for(j=myHaffCode[i].start;j<n;j++){ printf("%d",myHaffCode[i].bit[j]);
}
printf("\n");
} }
haffman哈夫曼编码的实现的更多相关文章
- 哈夫曼(huffman)树和哈夫曼编码
哈夫曼树 哈夫曼树也叫最优二叉树(哈夫曼树) 问题:什么是哈夫曼树? 例:将学生的百分制成绩转换为五分制成绩:≥90 分: A,80-89分: B,70-79分: C,60-69分: D,<60 ...
- java 哈夫曼编码
//哈夫曼树类 public class HaffmanTree { //最大权值 ; int nodeNum ; //叶子结点个数 public HaffmanTree(int n) { this. ...
- c++实验8 哈夫曼编码-译码器
哈夫曼编码-译码器 此次实验的注释解析多加不少---若对小伙伴们有帮助 希望各位麻烦点个关注 多谢 1.哈夫曼树构造算法为: (1)由给定的n个权值{w1,w2,…,wn}构造n棵只有根结点的二叉树, ...
- (转载)哈夫曼编码(Huffman)
转载自:click here 1.哈夫曼编码的起源: 哈夫曼编码是 1952 年由 David A. Huffman 提出的一种无损数据压缩的编码算法.哈夫曼编码先统计出每种字母在字符串里出现的频率, ...
- 数据结构图文解析之:哈夫曼树与哈夫曼编码详解及C++模板实现
0. 数据结构图文解析系列 数据结构系列文章 数据结构图文解析之:数组.单链表.双链表介绍及C++模板实现 数据结构图文解析之:栈的简介及C++模板实现 数据结构图文解析之:队列详解与C++模板实现 ...
- HDU2527 哈夫曼编码
Safe Or Unsafe Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)To ...
- *HDU1053 哈夫曼编码
Entropy Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Sub ...
- YTU 3027: 哈夫曼编码
原文链接:https://www.dreamwings.cn/ytu3027/2899.html 3027: 哈夫曼编码 时间限制: 1 Sec 内存限制: 128 MB 提交: 2 解决: 2 ...
- 使用F#来实现哈夫曼编码吧
最近算法课要求实现哈夫曼编码,由于前面的问题都是使用了F#来解决,偶然换成C#也十分古怪,报告也不好看,风格差太多.一开始是打算把C#版本的哈夫曼编码换用F#来写,结果写到一半就觉得日了狗了...毕竟 ...
随机推荐
- UBuntu14.04下安装和卸载Qt5.3.1
安装: 1. Qt5.3.1下载地址为:http://qt-project.org/,选择”Qt 5.3.1 for Linux 32-bit”版本,文件名是”qt-opensource-linux- ...
- Mac下Python安装目录
/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages
- quartz 实现调度任务 SchedulerManager
package cn.com.do1.component.common.util; import org.quartz.*; import org.quartz.impl.StdSchedulerFa ...
- vs2010程序运行出错 link : fatal error lnk1123: 转换到 coff 期间失败: 文件无效或损坏
vs2010程序运行出错 link : fatal error lnk1123: 转换到 coff 期间失败: 文件无效或损坏 2014-03-27 11:34杜_柏 | 浏览 36144 次 请问这 ...
- Java调用存储过程小结
学生在学习jdbc的时候,会问到怎么调用存储过程,现在将java调用oracle存储过程的示例总结如下.(关于调用sqlserver的存储过程将在下次进行小结请关注) 一:无返回值的存储过程 存储过程 ...
- 基于jquery响应式网站图片无限加载瀑布流布局
分享一款效果非常酷的jQuery瀑布流布局无限加载图片效果.整个页面采用响应式布局,图片采用jQuery.Lazyload延时加载技术,提升整个页面的加载速度.效果图如下: 在线预览 源码下载 实 ...
- 一款纯css3实现的动画按钮
今天给大家分享一款纯css3实现的动画按钮.第一排的按钮当鼠标经过的背景色动画切换,图标从右侧飞入,第二排的按钮当鼠标经过的时候边框动画切换,图标右侧飞入,效果非常好,一起看下效果图: 在线预览 ...
- Java字符串的格式化与输出
Java字符串的格式化与输出 在C语言中格式化输出能够通过printf()函数实现,在Java中无需借助第三方工具相同能够实现此功能.自Java SE5后,java也提供了C语言中printf()风格 ...
- Android集成银联支付,提示java.lang.UnsatisfieldLinkError错误
尽管解决方法很简单,但还是记录一下吧. 最近做银联支付(Android),官方给的demo是eclipse的.按照官方(https://open.unionpay.com/ajweb/product) ...
- Android ListView 长按列表弹出菜单
Android ListView 长按列表弹出菜单 设置长按菜单 listView.setOnCreateContextMenuListener(new View.OnCreateContextMen ...