哈夫曼编码(C语言)

这里写自定义目录标题


#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define maxval 10000.0
#define maxsize 100 //哈夫曼编码的最大位数
typedef struct
{
char ch;
float weight;
int lchild,rchild,parent;
}HTNode,*HufmTree;
typedef char **codetype ; //动态分配数组存储赫夫曼编码表

void Huffmanscanf(HufmTree &tree,int &n); //模块的功能为从键盘接收字符集大小n,以及n个字符和n个权值。
void Huffman(HufmTree &tree,int n);//建立哈夫曼树
void Huffmancode(HufmTree tree,codetype &code,int n);//根据哈夫曼树求出哈夫曼编码
void Decode(HufmTree tree,int n);//依次读入电文,根据哈夫曼树译码
void Decodestr(HufmTree tree,codetype code,int n);//依次读入字符串,根据哈夫曼数译码
void main()
{
char temp[5];
do
{
int n; //叶子数目
HufmTree tree; //哈夫曼树
int i;//循环变量
codetype code; //哈夫曼编码表
int grade;
printf(" ——哈夫曼编码——\n");
printf(“请选择自己需要进行的功能\n”);
printf(“1---------------初始化\n2---------------建树\n3---------------编码\n4---------------译码(0、1代码串->字符串)\n5---------------译码(字符串->0、1代码串)\n6---------------结束\n”);
do
{
printf(“选择: “);
scanf(”%d”,&grade);
getchar();
switch(grade)
{
case 1:Huffmanscanf(tree,n);break; //初始化
case 2:Huffman(tree,n);break;//建立哈夫曼树
case 3:Huffmancode(tree,code,n);//根据哈夫曼树求出哈夫曼编码
printf("【输出每个字符的哈夫曼编码】\n");
for(i=0;i<n;i++)
{
printf("%c: “,tree[i].ch);
printf(”%s “,code[i]);
printf(”\n");
}
break;
case 4: printf("【读入电文,并进行译码】\n");
Decode(tree,n);//依次读入电文,根据哈夫曼树译码
break;
case 5:printf("【读入字符串,并进行译码】\n");
Decodestr(tree,code,n);
break;
case 6: grade=0;break;
default:printf(“enter data error\n”);
}
}while(grade);
printf(“是否结束程序运行YES/NO: “);
gets(temp);
printf(”\n”);
}while(strcmp(temp,“YES”));
}
void Huffmanscanf(HufmTree &tree,int &n)
{
int i;
int m; //结点总数
char c;
float f;
printf("\n请输入字符个数: “);
scanf(”%d",&n);
getchar();
m=2n-1;
tree=(HufmTree)malloc(m
sizeof(HTNode));
for(i=0;i<m;i++) //初始化
{
tree[i].parent=0;
tree[i].lchild=-1;
tree[i].rchild=-1;
tree[i].weight=0.0;
}
printf("\n【依次读入前%d个结点的字符及权值(中间用空格隔开)】\n",n);
for(i=0;i<n;i++) //读入前n个结点的字符及权值
{
printf(“输入第%d个字符为和权值”,i+1);
scanf("%c",&c);
scanf("%f",&f);
getchar();
tree[i].ch=c;
tree[i].weight=f;
}
printf("-----初始化完成-----\n");
}
void Huffman(HufmTree &tree,int n)//建立哈夫曼树
{
int i,j,p1,p2;//p1,p2分别记住每次合并时权值最小和次小的两个根结点的下标
float small1,small2;
int m; //结点总数
m=2*n-1;
for(i=n;i<m;i++) //进行n-1次合并,产生n-1个新结点
{
p1=0;p2=0;
small1=maxval;small2=maxval; //maxval是float类型的最大值
for(j=0;j<i;j++)//选出两个权值最小的根结点
{
if(tree[j].parent==0)
{
if(tree[j].weight<small1)
{
small2=small1; //改变最小权、次小权及对应的位置
small1=tree[j].weight;
p2=p1;
p1=j;
}
else if(tree[j].weight<small2)
{
small2=tree[j].weight; //改变次小权及位置
p2=j;
}
}
}
if(p2>=n&&p1<n)
{
tree[p1].parent=i;
tree[p2].parent=i;
tree[i].lchild=p2;
tree[i].rchild=p1;
tree[i].weight=tree[p1].weight+tree[p2].weight;
}
else
{
tree[p1].parent=i;
tree[p2].parent=i;
tree[i].lchild=p1; //最小权根结点是新结点的左孩子
tree[i].rchild=p2; //次小权根结点是新结点的右孩子
tree[i].weight=tree[p1].weight+tree[p2].weight;
}

}
printf("------建树成功------\n");
}//huffman

void Huffmancode(HufmTree tree,codetype &code,int n)//根据哈夫曼树求出哈夫曼编码
//codetype code为求出的哈夫曼编码
//hufmtree tree为已知的哈夫曼树
{
int i,j,c,p,start;
code=(codetype)malloc(n*sizeof(char *)); //分配n个字符编码的头指针向量
char *cd; //缓冲变量
cd=(char )malloc(nsizeof(char)); //分配编码的工作空间
cd[n-1]=’\0’; //编码结束符
for(i=0;i<n;i++)
{
start=n-1;
c=i; //从叶结点出发向上回溯
p=tree[i].parent; //tree[p]是tree[i]的双亲
while(p!=0)
{
if(tree[p].lchild==c)
cd[–start]=‘1’; //tree[i]是左子树,生成代码’1’
else
cd[–start]=‘0’; //tree[i]是右子树,生成代码’0’
c=p;
p=tree[p].parent;
}
code[i]=(char *)malloc((n-start)*sizeof(char));
strcpy(code[i],&cd[start]); //从cd复制编码到code中

}
free(cd);

}//huffmancode

void Decode(HufmTree tree,int n)//依次读入电文,根据哈夫曼树译码
{
int i,j=0;
int m;
m=2*n-1; //结点总数
char b[maxsize];
char endflag=‘2’; //电文结束标志取2
i=m-1; //从根结点开始往下搜索
printf(“输入发送的编码(以’2’为结束标志):”);
gets(b);
printf(“译码后的字符为”);
while(b[j]!=‘2’)
{
if(b[j]‘1’)
i=tree[i].lchild; //走向左孩子
else if(b[j]
‘0’)
i=tree[i].rchild;//走向右孩子
else
{
printf("\nERROR\n"); //输入电文有错
break;
}
if(tree[i].lchild==-1) //tree[i]是叶结点
{
printf("%c",tree[i].ch);
i=m-1; //回到根结点
}
j++;
}
printf("\n");
if(tree[i].lchild!=-1&&b[j]!=‘2’) //电文读完,但尚未到叶子结点
printf("\nERROR\n"); //输入电文有错
}
void Decodestr(HufmTree tree,codetype code,int n)
{
int i,j;
char str[30];
gets(str);
for(i=0;str[i]!=’\0’;i++)
{
for(j=0;j<n;j++)
{
if(str[i]tree[j].ch)
{
printf("%s",code[j]);
break;
}
}
if(j
n)
{
printf(“ERROR\n”);
break;
}
}
printf("\n");
}

  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值