哈夫曼的c语言实现代码
我们设置一个结构数组HuffNode保存哈夫曼树中各结点的信息。根据二叉树的性质可知,具有n个叶子结点的哈夫曼树共有2n-1个结点,所以数组HuffNode的大小设置为2n-1。HuffNode结构中有weight,lchild,rchild和parent域。其中,weight域保存结点的权值,lchild和rchild分别保存该结点的左、右孩子的结点在数组HuffNode中的序号,从而建立起结点之间的关系。为了判定一个结点是否已加入到要建立的哈夫曼树中,可通过parent域的值来确定。初始时parent的值为-1。当结点加入到树中去时,该结点parent的值为其父结点在数组HuffNode中的序号,而不会是-1了。
求叶结点的编码:
该过程实质上就是在已建立的哈夫曼树中,从叶结点开始,沿结点的双亲链域回退到根结点,每回退一步,就走过了哈夫曼树的一个分支,从而得到一位哈夫曼码值。由于一个字符的哈夫曼编码是从根结点到相应叶结点所经过的路径上各分支所组成的0、1序列,因此先得到的分支代码为所求编码的低位,后得到的分支代码为所求编码的高位码。我们可以设置一个结构数组HuffCode用来存放各字符的哈夫曼编码信息,数组元素的结构中有两个域:bit和start。其中,域bit为一维数组,用来保存字符的哈夫曼编码,start表示该编码在数组bit中的开始位置。所以,对于第i个字符,它的哈夫曼编码存放在HuffCode[i].bit中的从HuffCode[i].start到n的bit位中。
/*-------------------------------------------------------------------------
*Name: 哈夫曼编码源代码。
*在Win-TC下测试通过
*实现过程:着先通过HuffmanTree()函数构造哈夫曼树,然后在主函数main()中
* 自底向上开始(也就是从数组序号为零的结点开始)向上层层判断,若在
* 父结点左侧,则置码为0,若在右侧,则置码为1。最后输出生成的编码。
*------------------------------------------------------------------------*/
#include<stdio.h>
#defineMAXBIT 100
#defineMAXVALUE 10000
#defineMAXLEAF 30
#defineMAXNODE MAXLEAF*2-1
typedefstruct
{
intbit[MAXBIT];
intstart;
}HCodeType; /*编码结构体*/
typedefstruct
{
intweight;
intparent;
intlchild;
intrchild;
}HNodeType; /*结点结构体*/
/*构造一颗哈夫曼树*/
voidHuffmanTree(HNodeTypeHuffNode[MAXNODE], intn)
{
/*i、j:循环变量,m1、m2:构造哈夫曼树不同过程中两个最小权值结点的权值,
x1、x2:构造哈夫曼树不同过程中两个最小权值结点在数组中的序号。*/
inti,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].lchild=-1;
}/*endfor*/
/*输入n个叶子结点的权值*/
for(i=0;i<n;i++)
{
printf("Pleaseinputweightofleafnode%d:\n",i);
scanf("%d",&HuffNode[i].weight);
}/*endfor*/
/*循环构造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;
}
elseif(HuffNode[j].weight<m2&&HuffNode[j].parent==-1)
{
m2=HuffNode[j].weight;
x2=j;
}
}/*endfor*/
/*设置找到的两个子结点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.weightandx2.weightinround%d:%d,%d\n",i+1,HuffNode[x1].weight,HuffNode[x2].weight); /*用于测试*/
printf("\n");
}/*endfor*/
}/*endHuffmanTree*/
intmain(void)
{
HNodeTypeHuffNode[MAXNODE]; /*定义一个结点结构体数组*/
HCodeTypeHuffCode[MAXLEAF], cd; /*定义一个编码结构体数组,同时定义一个临时变量来存放求解编码时的信息*/
inti,j,c,p,n;
printf("Pleaseinputn:\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;
else
cd.bit[cd.start]=1;
cd.start--; /*求编码的低一位*/
c=p;
p=HuffNode[c].parent; /*设置下一循环条件*/
}/*endwhile*/
/*保存求出的每个叶结点的哈夫曼编码和编码的起始位*/
for(j=cd.start+1;j<n;j++)
{HuffCode[i].bit[j]=cd.bit[j];}
HuffCode[i].start=cd.start;
}/*endfor*/
/*输出已保存好的所有存在编码的哈夫曼编码*/
for(i=0;i<n;i++)
{
printf("%d"sHuffmancodeis:",i);
for(j=HuffCode[i].start+1;j<n;j++)
{
printf("%d",HuffCode[i].bit[j]);
}
printf("\n");
}
getch();
return0;
}
相关文章
- excel宏编程 c语言,宏(巨集)
- 2022-09-06:以下go语言代码输出什么?A:Hi All;B:Hi go All;C:Hi;D:go All。 package main import
- R语言混合效应模型(mixed model)案例研究|附代码数据
- 【视频】CNN(卷积神经网络)模型以及R语言实现回归数据分析|附代码数据
- R语言中的Nelson-Siegel模型在汇率预测的应用|附代码数据
- Go语言知识查漏补缺|基本数据类型
- R语言实现拟合神经网络预测和结果可视化|附代码数据
- R语言预测期货波动率的实现:ARCH与HAR-RV与GARCH,ARFIMA模型比较|附代码数据
- R语言预测期货波动率的实现:ARCH与HAR-RV与GARCH,ARFIMA模型比较|附代码数据
- 【C 语言】文件操作 ( fseek 使用注意事项 | fseek 函数返回值分析 )
- 【C 语言】字符串拷贝 ( 字符串拷贝业务逻辑代码 | 分离 主函数 与 字符串拷贝 业务模型 )
- 【C 语言】C 项目开发代码规范 ( 形参合法性判断 | 函数返回值局部变量 | 函数中不用全局变量 | 函数中使用局部变量接收形参 | 函数返回值 | 形参作返回值 | 形参返回值处理 )
- 【C 语言】二级指针作为输入 ( 指针数组 | 指针数组排序 | 字符串排序 | strcmp 函数 )
- R语言中贝叶斯网络(BN)、动态贝叶斯网络、线性模型分析错颌畸形数据|附代码数据
- Go语言代码风格清晰、简单
- Go语言import导入包——在代码中使用其他的代码
- 轻松搞定Go语言连接MySQL(go连接mysql)
- 《代码英雄》第三季(8):C 语言之巨变
- c语言中十进制转二进制显示小工具的实现代码
- 用c语言根据可变参数合成字符串的实现代码
- PHP实现根据浏览器跳转不同语言页面代码
- k均值算法c++语言实现代码