zoukankan      html  css  js  c++  java
  • 求哈弗曼编码

      1 /********************************************************
      2 **         功能:求哈夫曼编码                          **
      3 **         时间:2015年5月10号                         **
      4 ********************************************************/
      5 #include<stdio.h>
      6 #include<stdlib.h>
      7 #include<string.h>
      8 #define MAXLEN 10000
      9 #define MAXVALUE 10000
     10 
     11 //结构体形式的字符包含的信息
     12 struct ChNode
     13 {
     14     int ascii;//存储字符的asci码
     15     char ch;//存储字符
     16     int count;//字符出现的次数
     17 };
     18 
     19 //定义哈夫曼树节点的结构体
     20 typedef struct HTNode
     21 {
     22     int weight;
     23     int parent,lchild,rchild;
     24 }HTNode;
     25 
     26 typedef char * *HuffmanCode;//定义指针类型的数据类型HuffmanCode
     27 typedef struct ChNode ChNode;//定义数据类型ChNode
     28 
     29 void Count_Times(char text[],ChNode freq[]);
     30 void Select(HTNode HT[],int i,int &s1,int &s2);
     31 void HuffmanCoding(HTNode HT[],HuffmanCode &HC,ChNode freq[],char text[]);
     32 
     33 void main()
     34 {
     35     ChNode freq[256];//存储字符出现次数的数组
     36     char text[MAXLEN];//将字符存储到数组中以后反编译时用
     37     HTNode HT[511];
     38     HuffmanCode HC;
     39     
     40     Count_Times(text,freq);
     41     HuffmanCoding(HT,HC,freq,text);
     42 }
     43 void Count_Times(char text[],ChNode freq[])
     44 {
     45     FILE *fp;//文件指针
     46     char chtmp;//临时存储从文件中读取的字符
     47     
     48     //跟freq数组赋初值
     49     for(int i=0;i<256;i++)
     50     {
     51         freq[i].ascii=i;
     52         freq[i].ch=(char)i;//强制转换为ascii码对应的字符型
     53         freq[i].count=0;
     54     }
     55     
     56     i=0;
     57     fp=fopen("a.txt","r");//以读的方式打开文件
     58     
     59     //统计文件里的字符的出现次数并赋值给text
     60     fscanf(fp,"%c",&chtmp);
     61     while(!feof(fp))
     62     {
     63         freq[chtmp].count++;
     64         fscanf(fp,"%c",&chtmp);
     65         text[i++]=chtmp;
     66         
     67     }
     68     fclose(fp);
     69     
     70     //以写方式打开文件并将统计结果输出到文件中
     71     fp=fopen("freq.txt","w");
     72     for(i=0;i<256;i++)
     73         fprintf(fp,"%d   %c   %d
    ",freq[i].ascii,freq[i].ch,freq[i].count);
     74     fclose(fp);
     75     
     76 }
     77 
     78 //选出两个权值最小的结点
     79 void Select(HTNode HT[],int i,int &s1,int &s2)
     80 {
     81     int m1,m2;//用来存储最小的两个权值
     82     
     83     m1 = m2 = MAXVALUE;
     84     s1 = s2 = -1;//用来存储最小权值的字符的序号
     85     
     86     for(int j = 0;j <= i;j ++)
     87     {
     88         //若一个字符的权值小于m1且parent为空(没有已经用过)
     89         if(HT[j].weight > 0 && HT[j].weight < m1 && HT[j].parent == -1)//s1存储的是字符中权值最小的序号
     90         {
     91             //权值比s1小,将s1赋值给s2再将字符序号给s1
     92             m2 = m1;
     93             s2 = s1;
     94             m1 = HT[j].weight;
     95             s1 = j;
     96         }
     97         else if(HT[j].weight > 0 && HT[j].weight < m2 && HT[j].parent == -1)//s2存储的是字符中权值第二小的序号
     98         {
     99             m2 = HT[j].weight;
    100             s2 = j;
    101 
    102         }
    103     }
    104     
    105     
    106 }
    107 
    108 void HuffmanCoding(HTNode HT[],HuffmanCode &HC,ChNode freq[],char text[])
    109 {
    110     //前256个单位有可能出现的字符将权值赋初值
    111     for(int i = 0;i < 256;i ++)
    112     {
    113         HT[i].weight = freq[i].count;
    114         HT[i].parent = -1;
    115         HT[i].lchild = -1;
    116         HT[i].rchild = -1;
    117     }
    118     //后面255的赋初值
    119     for(i = 256;i < 511;i ++)
    120     {
    121         HT[i].weight = 0;
    122         HT[i].parent = -1;
    123         HT[i].lchild = -1;
    124         HT[i].rchild = -1;
    125     }
    126 
    127     int s1,s2;
    128 
    129     //构造哈夫曼树的开始,构造parent节点
    130     for(i = 256;i < 511;i++)
    131     {
    132         Select(HT,i - 1,s1,s2);
    133         if(s1 != -1 && s2 != -1)
    134         {
    135             HT[i].weight = HT[s1].weight + HT[s2].weight;
    136             HT[s1].parent = i;
    137             HT[s2].parent = i;
    138             HT[i].lchild = s1;
    139             HT[i].rchild = s2;
    140         }
    141         else
    142         {
    143             HT[i - 1].parent = -1;
    144             break;
    145         }
    146     }
    147 
    148     //HuffmanTree.txt文件用来存放各个字符的权值、父母、孩子等信息
    149     FILE *fp;
    150     fp = fopen("HuffmanTree.txt","w");
    151     for(i = 0;i < 511;i ++)
    152         fprintf(fp,"(%d)    %d    %d    %d    %d
    ",i,HT[i].weight,HT[i].parent,HT[i].lchild,HT[i].rchild);
    153     fclose(fp);
    154 
    155     //HC相当于一个存放指针类型的数组,每一个元素相对应于一个字符编码数组的首地址
    156     HC = (HuffmanCode)malloc(256 * sizeof(char *));
    157     char cd[256];
    158     cd[255] = '';
    159     int c,f;
    160     int start;
    161     for(i =0 ;i < 256;i ++)
    162     {
    163         if(HT[i].parent != -1)
    164         {
    165             start = 255;
    166             //记录每个字符的编码,是0还是1
    167             for(c = i;f = HT[c].parent,f != -1;c = f,f = HT[f].parent)
    168             {
    169                 if(HT[f].lchild == c)
    170                     cd[--start] = '0';
    171                 else
    172                     cd[--start] = '1';
    173             }
    174             HC[i] = (char *)malloc((256 - start) * sizeof(char));
    175             strcpy(HC[i],&cd[start]);
    176         }
    177         else
    178         {
    179             HC[i] = NULL;
    180         }
    181     }
    182 
    183     //HuffmanCode.txt文件中记录字符出现的次数及其哈弗曼编码
    184     fp = fopen("HuffmanCode.txt","w");
    185     fprintf(fp,"ASCII值	字符	出现次数	编码 
    ");
    186     for(i = 0;i < 256;i ++)
    187         if(HC[i] != NULL)
    188             fprintf(fp,"%d	%c	%d	%s
    ",i,i,freq[i]);
    189         fclose(fp);
    190 
    191         //以对应的哈弗曼编码形式输出到文件中去
    192         fp = fopen("translate.txt","w");
    193         char ch;
    194         i =0;
    195         while(text[i] != '')
    196         {
    197             ch = text[i ++];
    198             fprintf(fp,"%s",HC[ch]);
    199         }
    200         fclose(fp);
    201 
    202 }
  • 相关阅读:
    Android引导页设计
    QQ5.0左侧滑动显示效果
    QQ左侧滑动显示之按钮切换
    QQ左侧滑动显示之自定义属性
    HDU 4009——Transfer water——————【最小树形图、不定根】
    HDU 2121——Ice_cream’s world II——————【最小树形图、不定根】
    POJ 3164——Command Network——————【最小树形图、固定根】
    HDU 5532——Almost Sorted Array——————【技巧】
    UVA 10462 —— Is There A Second Way Left?——————【最小生成树、kruskal、重边】
    HDU 4081—— Qin Shi Huang's National Road System——————【次小生成树、prim】
  • 原文地址:https://www.cnblogs.com/banshaohuan/p/4500696.html
Copyright © 2011-2022 走看看