Huffman树编码和译码

目标功能:

从键盘接收一串电文字符,输出对应的编码,同时,能翻译由哈夫曼编码生成的代码串,输出对应的电文字符串。

  1. 构造一棵哈夫曼树;
  2. 输出哈夫曼树的中序遍历序列(字符及其权值);
  3. 实现哈夫曼编码,并用哈夫曼编码生成的代码串进行译码

原理分析:

首先,为了构造哈夫曼树,我们需要统计每个字符出现的频率,并将它们放入一个优先队列中,队列中的每个元素表示一个字符及其出现的频率。然后,我们可以通过取出队列中频率最小的两个元素,将它们组合成一个新节点,并将新节点放回优先队列。这个过程重复执行,直到队列中只剩下一个元素,即哈夫曼树的根节点。

接下来,我们可以使用中序遍历算法输出哈夫曼树的中序遍历序列,其中包括每个字符及其频率。

然后,我们就可以用哈夫曼编码生成代码串,哈夫曼编码的规则是将哈夫曼树中的每个节点标记为0或1,路径中左转为0,右转为1。对于每个字符,我们可以从根节点开始,按照哈夫曼编码规则找到对应的叶子节点,将该节点的路径上的0和1记录下来,这就是该字符的哈夫曼编码。

最后,我们可以用哈夫曼编码来翻译代码串,即根据哈夫曼编码规则,从根节点开始,依次将代码串中的0和1翻译为对应的字符,直到结束。

代码:

#include<stdio.h>
#include<conio.h>
#define MAXVALUE 10000           //定义最大权值 
#define MAXLEAF 30               //定义哈夫曼树中叶子节点个数 
#define MAXNODE MAXLEAF*2-1
#define MAXBIT 50
#define NULL 0
typedef struct node{
	char letter;
	   int weight;               //结点的权值 
	   int parent;               //结点的双亲 
	   int lchild;               //结点的左孩子 
	   int rchild;              //结点的右孩子 
}HNodeType;
typedef struct{
	char letter;
	   int bit[MAXBIT];
	   int start;
}HCodeType;
typedef struct{
	char s;
	   int num;
}Message;
//哈夫曼树的构造算法
void HuffmanTree(HNodeType HuffNode[],int n,Message a[])
{
	int i,j,m1,m2,x1,x2,temp1;char temp2;
	for(i=0;i<2*n-1;i++)  //HuffNode[]初始化
	{
		HuffNode[i].letter=NULL;
		HuffNode[i].weight=0;
		HuffNode[i].parent=-1;
		HuffNode[i].lchild=-1;
		HuffNode[i].rchild=-1;
	 } 
	 for(i=0;i<n-1;i++)
	    for(j=i+1;j<n-1;j++)
	      if(a[j].num>a[i].num)
	      {
	      	temp1=a[i].num;a[i].num=a[j].num;a[j].num=temp1;
	      	temp2=a[i].s;a[i].s=a[j].s;a[j].s=temp2;
		  }
	for(i=0;i<n;i++)
	{
		HuffNode[i].weight=a[i].num;
		HuffNode[i].letter=a[i].s;
    }
    for(i=0;i<n-1;i++)   //构造哈夫曼树
	{
		m1=m2=MAXVALUE;
		x1=x2=0;
		for(j=0;j<n+i;j++)  //找出的两棵权值最小的子树
		{
			if(HuffNode[j].parent==-1&&HuffNode[j].weight<m1)
			{
				m2=m1;x2=x1;
				m1=HuffNode[j].weight;  x1=j;
			}
			else if(HuffNode[j].parent==-1&&HuffNode[j].weight<m2)
			{
				m2=HuffNode[j].weight;
				x2=j;
			}
		 } 
		 //将找出的两棵子树合并为一棵子树
		 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; 
	 } 
 } 
 //生成哈夫曼编码
 void HuffmanCode(int n,Message a[])
 {
 	HNodeType HuffNode[MAXNODE];
 	HCodeType HuffCode[MAXLEAF],cd;
 	int i,j,c,p;
 	char code[30],*m;
 	HuffmanTree(HuffNode,n,a);  //建立哈夫曼树
	 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;
		  } 
		  for(j=cd.start+1;j<n;j++)  //保存求出的每个结点的哈夫曼编码和编码的起始位
		  HuffCode[i].bit[j]=cd.bit[j];
		  HuffCode[i].start=cd.start; 
	  } 
	  printf(" 输出每个叶子的哈夫曼编码:\n");
	  for(i=0;i<n;i++)    //输出每个叶子结点的哈夫曼编码 
	  {
	  	HuffCode[i].letter=HuffNode[i].letter;
		printf(" %c:",HuffCode[i].letter);
		for(j=HuffCode[i].start+1;j<n;j++)
		printf(" %d",HuffCode[i].bit[j]);
		printf("\n"); 
	  }
	  printf(" 请输入电文(1/0):\n");
	  for(i=0;i<30;i++)code[i]=NULL;
	  scanf(" %s",&code); m=code;
	  c=2*n-2;
	  printf(" 输出哈夫曼译码:\n");
	  while(*m!=NULL)
	  {
	  	if(*m=='0')
	  	{
	  		c=i=HuffNode[c].lchild;
	  		if(HuffNode[c].lchild==-1&&HuffNode[c].rchild==-1)
	  		{
	  			printf("%c",HuffNode[i].letter);
	  			c=2*n-2;
			  }
		  }
		 if(*m=='1')
		  {
		  	c=i=HuffNode[c].rchild;
		  	if(HuffNode[c].lchild==-1&&HuffNode[c].rchild==-1)
		  	{  printf("%c",HuffNode[i].letter);
		  	   c=2*n-2;
			}
		  }
		  m++;
	   } 
	   printf("\n");
  } 
void main()
  {
  	Message data[30];
  	char s[100],*p;
  	int i,count=0;
  	printf("\n 请输入一些字符:");
	scanf("%s",&s);
	for(i=0;i<30;i++)
	{
		data[i].s=NULL;
		data[i].num=0;
	 } 
	 p=s;
	 while(*p)
	 {
	 	for(i=0;i<=count+1;i++)
	 	{
	 		if(data[i].s==NULL)
	 		{
	 			data[i].s=*p;data[i].num++;count++;break;
			 }
			 else if(data[i].s==*p)
			 {
			 	data[i].num++;break;
			 }
		 }
		 p++;
	 }
	 printf("\n");
	 printf(" 不同的字符数:%d\n",count);
	 for(i=0;i<count;i++)
	 {  printf(" %c ",data[i].s);
	    printf(" 权值:%d",data[i].num);
	    printf("\n");
	 }
	 HuffmanCode(count,data);
	 getch();
  }
 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Melina_劉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值