1. 程式人生 > >建立哈夫曼樹並進行哈夫曼編碼與哈夫曼譯碼

建立哈夫曼樹並進行哈夫曼編碼與哈夫曼譯碼

  • 圖例
    這裡寫圖片描述 這裡寫圖片描述 這裡寫圖片描述 這裡寫圖片描述
    以上圖例解釋:
    這裡寫圖片描述
    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); }