算法源码之哈弗曼编、译码

学习有三种境界
1.理解了
2.比较了
3.思考了
很多时候我们都只是停留在第一阶段,光理解了,还不够,无法给我们留下深刻的印象。
本文实现了对26个小写英文字母在日常生活中出现的次数构(权重)造哈夫曼树,并根据输入的英文进行编译码
 
#include<stdio.h>
#include<string.h>
#include<malloc.h>

#define MAX  5000

typedef char *HuffmanCode[30];
typedef struct BTNode{
  char letter;
  int parent;
  int weight;
  int LChild;
  int RChild;
}BTNode;

void select(BTNode BTree[],int *s1,int *s2,int r){
	int i,j,min1,min2;
	min1=min2=MAX;
	for(i=0;i<r;i++){
		if(min1>BTree[i].weight&&BTree[i].parent==-1){
		 *s1=i;
		 min1=BTree[i].weight;
		}
	}
	for(j=0;j<r;j++){
		if(min2>BTree[j].weight&&BTree[j].parent==-1&&(*s1)!=j){
		 *s2=j;
		 min2=BTree[j].weight;
		}
	}
}

void crtHuffmanTree(BTNode BTree[],int w[],char word[],int n){
  int i,j,m,s1,s2;
  m=2*n-1;
  for(i=0;i<n;i++){  //初始化哈弗曼树
   BTree[i].letter=word[i];
   BTree[i].parent=-1;
   BTree[i].weight=w[i];
   BTree[i].LChild=-1;
   BTree[i].RChild=-1; //初始化完毕
  }
  for(j=n;j<m;j++){  //开始创建非叶子结点
   select(BTree,&s1,&s2,j);
   BTree[j].weight=BTree[s1].weight+BTree[s2].weight;
   BTree[j].LChild=s1;
   BTree[j].RChild=s2;
   BTree[s1].parent=j;
   BTree[s2].parent=j;
   BTree[j].parent=-1;
  }
 /* for(i=0;i<m;i++){
  printf("%d ",BTree[i].weight);
  if(i%10==0)
	  printf("\n");
  }*/
}

void crtHuffmanCode(BTNode BTree[],HuffmanCode hc,int n){
   int i,start,p,c;
	char *cd;
                   //给编码分配存储空间,使cd指向数组的首地址
  cd=(char*)malloc((n+1)*sizeof(char));
  cd[n-1]='\0';
  printf("每个英文字母的哈弗曼编码如下:\n");

  for(i=0;i<n;i++){
   start=n-1;
   c=i;
   p=BTree[i].parent;//依次在哈弗曼树中找每个元素的父母
   
   while(p!=-1){   //直到找到根结点为止
    start--;       //每减少一层,start减一
	if(BTree[p].LChild==c)cd[start]='0';
	else cd[start]='1';
	c=p;          //保存当前结点,以便上一层确认该结点是左孩子还是右孩子
	p=BTree[p].parent;//继续找上一层
   }

   hc[i]=(char*)malloc((n-start)*sizeof(char));
   strcpy(hc[i],&cd[start]);
  // printf("概率为:");
   printf("%c ",BTree[i].letter);
   printf("的编码为:");
   printf("%s \n",hc[i]);
  }
  
  free(cd);
}
//对所输入的字符序列进行编码
void crtStringCode(BTNode BTree[],HuffmanCode hc,int n){
	int i=0,j;
	char c[20],ch;
     printf("输入要译码的字符序列:\n");
	 for(;;){
	  ch= getchar();
	   if(ch==10){
		   c[i]='\0';
	    break;
	   }
	   c[i]=ch;
	   i++;
	 };
	 printf("你所输入的字符序列的编码为:\n");
	 for(i=0;i<(signed)strlen(c);i++){
	 for(j=0;j<n;j++){
	  if(c[i]==BTree[j].letter)
	  {
		  printf("%s",hc[j]);
	      break;
	  }
	 }
	 }
	 printf("\n");
}
//对所输入的码字进行译码
void translateCode(BTNode BTree[],HuffmanCode hc,int n){
      int i=0,ch;
	  char d[100];
	  int p;
      printf("输入码符号序列:\n");
	  for(;;){
	    ch=getchar();
		if(ch==10){
		  d[i]='\0';
		  break;
		}
		d[i]=ch;
		i++;
	  }
	  printf("译码得:\n");
	 /* for(i=0;i<(unsigned)strlen(d);i++){
	    printf("%c",d[i]);
	  }*/
	  p=2*n-2;
	  //printf("%d",BTree[p].parent);
	  for(i=0;i<(signed)strlen(d);i++){
		  if('0'==d[i]){
			  p=BTree[p].LChild;
           if(BTree[p].LChild==-1&&BTree[p].RChild==-1){
		   printf("%c",BTree[p].letter);
           p=2*n-2;
		  }
		  }
		  else if('1'==d[i]){
			   p=BTree[p].RChild;
		   if(BTree[p].LChild==-1&&BTree[p].RChild==-1){
		   printf("%c",BTree[p].letter);
           p=2*n-2;
		   }
		    
		  }
	  }
    printf("\n");
}

void main(){
	BTNode BTree[2*27-1];
	HuffmanCode hc;
	int n=27;
 
 int w[27]={186,64,13,22,32,103,21,15,47,57,1,5,
	       32,20,57,63,15,1,48,51,80,23,8,18,1,16,1};
 char word[27]={' ','a','b','c','d','e','f','g','h','i',
	            'j','k','l','m','n','o','p','q','r','s',
				't','u','v','w','x','y','z'};
 crtHuffmanTree(BTree,w,word,n);
 crtHuffmanCode(BTree,hc,n);
 crtStringCode(BTree,hc,n);
 translateCode(BTree,hc,n);
}


 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值