建立哈夫曼樹並進行哈夫曼編碼與哈夫曼譯碼
阿新 • • 發佈:2019-01-04
- 圖例
以上圖例解釋:
c語言實現程式碼:
#include<stdio.h>
#include<malloc.h>
#include<string.h>
#define N 100
#define M 2*N-1
typedef struct
{
int weight,parent,lchild,rchild;
}hnode;
void select(hnode htree[] ,int i,int *s1,int *s2)//在前i項中找到權值最小的結點將其下標給s1,s2
{
*s1=0;
while (htree[*s1].parent!=-1)//找到待掃描結點第一個parent為-1的結點作為最小基準點
(*s1)++;
for(int j=0;j<=i;j++)
{
if(htree[j].weight<htree[*s1].weight&&htree[j].parent==-1)
{
*s1=j;
}
}//找出權值最小的結點的下標;
if(*s1>=0&&*s1<i-1)//找到第二個 parent=-1的結點作為最為次小基準點
{
(*s2)=(*s1)+1;
while(htree[*s2].parent!=-1)
(*s2)++;
}
else
{
(*s2)=(*s1)-1;
while(htree[*s2].parent!=-1)
(*s2)--;
}
for(int j=0;j<=i;j++)
{
if(htree[j].weight<htree[*s2].weight&&j!=*s1&&htree[j].parent==-1 )
*s2=j;
}
if(htree[*s1].lchild=-1&&htree[*s2].lchild!=-1)
{
int a=*s1;
int b=*s2;
*s1=b;
*s2=a;
}
}
void create_haffman_tree(hnode htree[],int value[],int n)
{
//初始化前n個結點
for(int i=0;i<n;i++)
{
printf("%d ",value[i]);
}
for(int i=0;i<n;i++)
{
htree[i].weight=value[i];
htree[i].parent=htree[i].lchild=htree[i].rchild=-1;
}
//初始化後n-1個結點
for(int i=n;i<2*n-1;i++)
htree[i].weight=htree[i].parent=htree[i].lchild=htree[i].rchild=-1;
for(int i=n;i<2*n-1;i++)//構造後n-1個結點;
{
int s1,s2;
select(htree,i-1,&s1,&s2);
htree[i].weight=htree[s1].weight+htree[s2].weight;
htree[i].lchild=s1;
htree[i].rchild=s2;
htree[s1].parent=htree[s2].parent=i;
}
}
void haffman_encoding(hnode htree[],char *haffmancode[],int n)
{
char *cd;
int start,c,p;
cd=(char *)malloc(n*sizeof(char));
cd[n-1]='\0';//首先存放編碼結束符;
for(int i=0;i<n;i++)
{
start=n-1;
c=i;
p=htree[i].parent;
while(p!=-1)
{
--start;
if(htree[p].lchild==c)
cd[start]='0';
else
cd[start]='1';
c=p;p=htree[p].parent;
}
haffmancode[i]=(char *)malloc((n-start)*sizeof(char));
strcpy(haffmancode[i],&cd[start]);
}
}
void haffmandecoding(hnode htree[],char *haffmancode[],int n,char string[])
{
printf("請輸入二進位制碼串:\n");
char s[n];
scanf("%s",s);
int flag=0;
char tem[n];
printf("譯碼後的檔案:\n");
for(int i=0;i<strlen(s);i++)
{
tem[flag]=s[i];
tem[++flag]='\0';
for(int j=0;j<n;j++)
{
if(!strcmp(tem,haffmancode[j]))
{
printf("%c",string[j]);
flag=0;
}
if(j==n-1&&i==strlen(s)-1)
{
printf("無法完成譯碼!");
return ;
}
}
}
}
int main(void)
{
char string[N];
int value[N];
printf("請輸入字符集:\n");
scanf("%s",string);
int n=strlen(string);
hnode htree[n*2-1];
char *haffmancode[n];//存放每個字元的哈夫曼編碼的頭指標。
printf("請輸入字符集所對應的權值\n");
for(int j=0;j<n;j++)
scanf("%d",&value[j]);
//getlen(string)個字元,最後生成的哈夫曼樹將有2*getlen(string)-1個結點;
create_haffman_tree(htree,value,n);
printf("\n");
for(int i=0;i<n*2-1;i++)
haffman_encoding(htree,haffmancode,n);
for(int j=0;j<n;j++)
printf("%c的哈夫曼編碼為:%s\n",string[j],haffmancode[j]);
haffmandecoding(htree,haffmancode,n,string);
}