学习有三种境界
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);
}