標(biāo)題: 哈夫曼編碼源程序 [打印本頁(yè)]

作者: liufendou    時(shí)間: 2017-5-27 17:24
標(biāo)題: 哈夫曼編碼源程序
// 哈夫曼編碼(算法)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
typedef char *HuffmanCode;  //動(dòng)態(tài)分配數(shù)組,存儲(chǔ)哈夫曼編碼
typedef struct
{
        unsigned int weight;  //用來(lái)存放各個(gè)結(jié)點(diǎn)的權(quán)值
        unsigned int parent,LChild,RChild;  //指向雙親、孩子結(jié)點(diǎn)的指針
} HTNode, *HuffmanTree;  //動(dòng)態(tài)分配數(shù)組,存儲(chǔ)哈夫曼樹//選擇兩個(gè)parent為0,且weight最小的結(jié)點(diǎn)s1和s2
char alpha[53] = {'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',
                  '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'};
char alpha_1[53];
int num1[52] = {0};
int num2[52] = {0};
double num3[52] = {0};
int k = 0;
double add[52];
double HX = 0.0;
double MX = 0.0;
void Select(HuffmanTree *ht,int n,int *s1,int *s2)
{
        int i,min;
    for(i=1; i<=n; i++)
        {
         if((*ht).parent==0)
         {
             min=i;
       break;
           }
        }
    for(i=1; i<=n; i++)
        {
         if((*ht).parent==0)
         {
                   if((*ht).weight<(*ht)[min].weight)
                    min=i;
     }
    }
    *s1=min;
    for(i=1; i<=n; i++)
        {
           if((*ht).parent==0 && i!=(*s1))
           {
                   min=i;
        break;
       }
        }
    for(i=1; i<=n; i++)
          {
             if((*ht).parent==0 && i!=(*s1))
         {
                if((*ht).weight<(*ht)[min].weight)
                 min=i;
         }
        }
    *s2=min;
}//構(gòu)造哈夫曼樹ht。w存放已知的n個(gè)權(quán)值
void CrtHuffmanTree(HuffmanTree *ht,int *w,int n)
{
int m,i,s1,s2;
    m=2*n-1;
    *ht=(HuffmanTree)malloc((m+1)*sizeof(HTNode));
    for(i=1; i<=n; i++)  //1--n號(hào)存放葉子結(jié)點(diǎn),初始化
        {
                  (*ht).weight=w;
        (*ht).LChild=0;
        (*ht).parent=0;
        (*ht).RChild=0;
        }
    for(i=n+1; i<=m; i++)
        {
                (*ht).weight=0;
        (*ht).LChild=0;
        (*ht).parent=0;
        (*ht).RChild=0;
        } //非葉子結(jié)點(diǎn)初始化
  //  printf("\nHuffmanTree: \n");
    for(i=n+1; i<=m; i++)   //創(chuàng)建非葉子結(jié)點(diǎn),建哈夫曼樹
        {
  //在(*ht)[1]~(*ht)[i-1]的范圍內(nèi)選擇兩個(gè)parent為0
        //且weight最小的結(jié)點(diǎn),其序號(hào)分別賦值給s1、s2
        Select(ht,i-1,&s1,&s2);
        (*ht)[s1].parent=i;
        (*ht)[s2].parent=i;
        (*ht).LChild=s1;
        (*ht).RChild=s2;
        (*ht).weight=(*ht)[s1].weight+(*ht)[s2].weight;
   //     printf("%d (%d, %d)\n",(*ht).weight,(*ht)[s1].weight,(*ht)[s2].weight);
        }
    printf("\n");
} //哈夫曼樹建立完畢//從葉子結(jié)點(diǎn)到根,逆向求每個(gè)葉子結(jié)點(diǎn)對(duì)應(yīng)的哈夫曼編碼
void CrtHuffmanCode(HuffmanTree *ht, HuffmanCode *hc, int n,char str[],double num[],double HX)
{
        int shu[n];
        char *cd;
    int i,start,p;
    unsigned int c;
    hc=(HuffmanCode *)malloc((n+1)*sizeof(char *));  //分配n個(gè)編碼的頭指針
    cd=(char *)malloc(n*sizeof(char));  //分配求當(dāng)前編碼的工作空間
    cd[n-1]='\0';  //從右向左逐位存放編碼,首先存放編碼結(jié)束符
    for(i=1; i<=n; i++)  //求n個(gè)葉子結(jié)點(diǎn)對(duì)應(yīng)的哈夫曼編碼
        {
          start=n-1;  //初始化編碼起始指針
    for(c=i,p=(*ht).parent; p!=0; c=p,p=(*ht)[p].parent)  //從葉子到根結(jié)點(diǎn)求編碼
           if( (*ht)[p].LChild==c)
            cd[--start]='1';  //左分支標(biāo)0
    else
            cd[--start]='0';  //右分支標(biāo)1
    hc=(char *)malloc((n-start)*sizeof(char));  //為第i個(gè)編碼分配空間
    strcpy(hc,&cd[start]);
        }
    free(cd);
    for(i=1; i<=n; i++)
          printf("HFMC  %c  is  %s\n",str,hc);
          for(i=1; i<=n; i++)
          {
              shu = strlen(hc);         //測(cè)出碼長(zhǎng)
              MX += shu*num3;    //計(jì)算平均碼長(zhǎng)
          }
              MX = HX/MX;//計(jì)算效率
          printf("\n編碼效率n     %f\n",MX);
    printf("\n");
}
int countchar(char str[],char a,int n_value)
{
    int n=0;
    int i = 0;
    while(i < n_value)
        {
        if((str) == a)
        n++;
        i++;
    }
    return n;
}
int main()
{
     HuffmanTree HT;
     HuffmanCode HC;
     int *w,i,wei,m,value = 0,count = 0,n1 = 0,n2 = 0,j = 0,n = 0;
     char data;
   
     FILE *fp=fopen("in.txt","r");
         if(!fp)
         {
                  printf("can't open file\n");
                  return -1;
         }
         while(!feof(fp))
         {
                  value++;
                 data=fgetc(fp);
              printf("%c",data);
              if(data>='a'&&data<='z'||data>='A'&&data<='Z')
                  n1++;
             else if(data>='0'&&data<='9')
                  n2++;
         }
         printf("\n字母:%d\n",n1);
         printf("\n");
         fclose(fp);
         char disbuf[value];
         FILE *fq=fopen("in.txt","r");
        if(!fq)
        {
           printf("can't open file\n");
           return -1;
        }
          while(count <= value)
    {
          fscanf(fq,"%c",&disbuf[count]);
          count++;
        }
    fclose(fq);
    printf("\n");
    for(j = 0; j < 52; j++)
    num1[j] += countchar(disbuf, alpha[j],n1);//找出各個(gè)字母的個(gè)數(shù)
   
    for( i = 0; i < 52; i++ ) //求每個(gè)字母的概率
    {
             add= double(num1)/double(n1);
    }
   
   
    for( i = 0,j = 1;i < 26; i++)
    {
        printf("字母%c\t\t數(shù)量%d\t概率%0.3f\t",alpha,num1,add);
             printf("字母%c\t\t數(shù)量%d\t概率%0.3f\t",alpha[i+26],num1[i+26],add[i+26]);
    }
   
   for(i = 0,j = 1; i < 52; i++)//把不為零的字母統(tǒng)計(jì)出來(lái),統(tǒng)計(jì)他們的個(gè)數(shù)與符號(hào)
   {
            if(num1 != 0)
            {  
                    n++;
                    num2[j] = num1;
                    alpha_1[j] = alpha;
                    j++;
            }
   }
   for( i = 0,j = 1; i < 52; i++ ) //把不為零的字母概率挑選出來(lái) ,計(jì)算信源熵
   {
     if(num1 != 0)
            {  
               HX += add*log10(add);
               num3[j] = add;        //挑選出有概率的字符和其概率;  
               j++;
            }
   }
    HX =  - HX/log10(2);        //計(jì)算信源熵  
        printf("\n信源熵H(X)    %f\n",HX);
       
    w=(int *)malloc((n+1)*sizeof(int));
    for(i=1; i<=n; i++)
        {
        w= num2 ;
        }
    CrtHuffmanTree(&HT,w,n);
    CrtHuffmanCode(&HT,&HC,n,alpha_1,num3,HX);
   






歡迎光臨 (http://www.torrancerestoration.com/bbs/) Powered by Discuz! X3.1