zoukankan      html  css  js  c++  java
  • 哈夫曼编译系统

      1 /*
      2  哈夫曼编码C语言实现 
      3 */
      4 //    n个数字,对应n个权值
      5 //  n作为主输入参数,确定需要编码的数量
      6 //    输入n个权值,进行加权求解 
      7 //    求解最小生成树 
      8 // 
      9 //    涉及数据成员:
     10 //        weight  权值
     11 //        parent  父节点
     12 //         
     13 #include<stdio.h>
     14 #include<stdlib.h> 
     15 #include<string>
     16 #define TREELEN 100
     17 #define MAXVALUE 99999
     18 struct HuffmanNode{
     19     int weight;
     20     int parent;
     21     int lchild;
     22     int rchild;
     23     public: HuffmanNode(int w=0,int p=-1):weight(w),parent(p)
     24     {lchild=-1;
     25     rchild=-1;} 
     26 }Nodes[TREELEN]; 
     27 struct HuffmanResult{
     28     int weight;
     29     int *bit;
     30     int length; 
     31 }* huffman;
     32 /*
     33 函数实现功能:完成哈夫曼树
     34               完成哈夫曼编码 
     35 n 代表需要编码数据的个数
     36 huffman表示要存储最终结果的数组,其中Weight存放其权值,maxbit 存放其结果 
     37             length表示编码长度 
     38 */ 
     39 void HuffmanAnswer(int n)
     40 {
     41     //申请n个保存编码 的空间 
     42     huffman=(HuffmanResult*)malloc(n*sizeof(HuffmanResult));
     43     int min1=0,min2=0;//每次寻找两个最小值,必须未访问,判断方式就是其父节点不为-1 
     44     int added=0;
     45     int i=0,j=0;
     46     int del1=0,del2=0;
     47     int bitlen=0;
     48     int* maxbit=(int*)malloc(n*sizeof(int));
     49     for(i=0;i<n;i++)
     50     {
     51         huffman[i].weight=Nodes[i].weight;
     52     }
     53     while(true)
     54     {
     55         min2=min1=MAXVALUE;
     56         del1=del2=0;
     57         for(i=0;i<n+added;i++)
     58         {
     59             //min1保留最小值,min2保存仅比Min1大的值 
     60             //del1 记录权值为min1的节点序号,del2记录权值为min2的节点序号 
     61             if(Nodes[i].parent==-1&&Nodes[i].weight<min2)
     62             {
     63                 if(Nodes[i].weight<min1)
     64                 {
     65                     min2=min1;
     66                     del2=del1;
     67                     min1=Nodes[i].weight;
     68                     del1=i;
     69                 }
     70                 else{
     71                     min2=Nodes[i].weight;
     72                     del2=i;
     73                 }
     74             }
     75         }    
     76         if(min2==MAXVALUE)break;//处理完毕,跳出循环 
     77         Nodes[del1].parent=n+added;
     78         Nodes[del2].parent=n+added;
     79         Nodes[n+added].weight=min1+min2;
     80         Nodes[n+added].lchild=del1;
     81         Nodes[n+added].rchild=del2;
     82         added+=1;
     83     }
     84     int t=0;
     85     for(i=0;i<n;i++)
     86     {
     87         bitlen=0;
     88         j=i;
     89         while(Nodes[j].parent!=-1) 
     90         {
     91             t=j;
     92             j=Nodes[j].parent;
     93             if(Nodes[j].lchild==t)
     94                 maxbit[bitlen]=0;
     95             else maxbit[bitlen]=1;
     96             bitlen++;
     97         }
     98         huffman[i].bit=(int*)malloc(bitlen*sizeof(int));
     99         for(j=0;j<bitlen;j++)
    100         huffman[i].bit[bitlen-j-1]=maxbit[j];
    101         huffman[i].length=bitlen;
    102     } 
    103     printf("哈夫曼树及哈夫曼编码成功!
    ");
    104 }
    105 //index 索引序号 
    106 //h    深度 
    107 /*
    108 函数功能 :
    109         打印空格 
    110 */ 
    111 void printSpace(int cnt,FILE* fout)
    112 {
    113     for(int i=0;i<cnt;i++){
    114     printf("    ");
    115     fprintf(fout,"    ");
    116     } 
    117 } 
    118 /*
    119 函数功能:
    120     打印哈夫曼树(凹陷法) 
    121 */ 
    122 void printHuffTree(int index,int h,FILE* fout)
    123 {
    124     if(Nodes[index].lchild==-1&&Nodes[index].rchild==-1)
    125     {
    126         printSpace(h,fout);
    127         fprintf(fout,"%d
    ",index);
    128         printf("%d
    ",index);
    129         return;
    130     }
    131     printSpace(h,fout);
    132     printf("%d
    ",index);
    133     fprintf(fout,"%d
    ",index);
    134     printHuffTree(Nodes[index].lchild,h+1,fout);
    135     printHuffTree(Nodes[index].rchild,h+1,fout);
    136 }
    137 /*
    138     译码功能:
    139         从文件中读取编码。
    140         手动输入编码,需要知道长度 
    141 */ 
    142 void HuffmanDecoding(int n)
    143 {
    144     int choice,i,len;
    145     char codestore[1000];
    146     char code;
    147     int tcode;
    148     char filename[60];
    149     char savename[60];
    150     
    151     FILE *fin;
    152     FILE *fp;
    153     printf("输入译码要保存的文件名(txt或bin文档):") ;
    154     scanf("%s",savename);
    155     if(!(fin=fopen(savename,"w")))
    156     {
    157         printf("保存文档路径打开失败!") ;
    158         return;
    159     } 
    160     printf("请选择获取编码的方式:
    "); 
    161     printf("		1--从文件中读取编码并翻译
    "); 
    162     printf("		2--手动输入编码并翻译
    ");
    163     scanf("%d",&choice);
    164     if(choice==1)
    165     {
    166         printf("输入编码源文件名(txt或bin文档): ");
    167         scanf("%s",filename);
    168         
    169         if( !(fp=fopen(filename,"r"))) 
    170         {
    171             printf("源码文档打开失败!") ;
    172             return;
    173         }
    174         tcode=2*n-2;
    175         while(!feof(fp))
    176         {
    177             code=fgetc(fp);
    178             if(code=='0')
    179                 tcode=Nodes[tcode].lchild;
    180             else if(code=='1')
    181             tcode=Nodes[tcode].rchild;
    182             if(Nodes[tcode].lchild==-1&&Nodes[tcode].rchild==-1)
    183             {
    184                 printf("%d ",tcode);// 
    185                 fprintf(fin,"%4d",tcode);
    186                 tcode=2*n-2;
    187             }
    188         }
    189         fclose(fp);
    190         printf("
    译码成功!
    ") ;
    191     }
    192     else if(choice==2)
    193     {
    194         printf("输入编码:
    "); 
    195         scanf("%s",codestore);
    196         len=strlen(codestore);
    197         i=0;
    198         tcode=2*n-2;
    199         while(i<len)
    200         {
    201             if(codestore[i]=='0')
    202             tcode=Nodes[tcode].lchild;
    203             else if(codestore[i]=='1')tcode=Nodes[tcode].rchild;
    204             if(Nodes[tcode].lchild==-1&&Nodes[tcode].rchild==-1)
    205             {
    206                 printf("%d ",tcode);// 
    207                 fprintf(fin,"%4d",tcode);
    208                 tcode=2*n-2;
    209             }
    210             i++;
    211         }
    212     }
    213     fclose(fin);
    214     printf("
    译码成功!
    ") ;
    215 }
    216 void PrintHuffCode(int n)
    217 {
    218     //输出所有权值所对应编码 
    219     int choice,i,j; 
    220     char savefile[60];
    221     int flag=0; 
    222     FILE *fin;
    223     printf("是否要保存到文件中?
    ");
    224     printf("		1: 是
    		2: 不
    ");
    225     scanf("%d",&choice);
    226     
    227     if(choice==1)
    228     {
    229         printf("输入编码要保存到文件名:");
    230         scanf("%s",savefile);
    231         if(!(fin=fopen(savefile,"w"))){
    232             printf("保存路径有误!
    ");
    233             return;
    234         }
    235         flag=1;
    236     }
    237     printf("权值	编码长度	编码
    ");
    238     if(flag==1)fprintf(fin,"权值	编码长度	编码
    ");
    239     for(i=0;i<n;i++)
    240     {
    241         printf("%3d	%d		",huffman[i].weight,huffman[i].length);
    242     if(flag==1)    fprintf(fin,"%3d	%d		",huffman[i].weight,huffman[i].length);
    243         for(j=0;j<huffman[i].length;j++)
    244         {
    245         printf("%d",huffman[i].bit[j]);
    246     if(flag==1)    fprintf(fin,"%d",huffman[i].bit[j]);
    247         }
    248         printf("
    ");
    249     }
    250     if(flag==1)
    251     {
    252         printf("保存到文件%s成功.
    ",savefile);
    253     } 
    254 }
    255 void menu()
    256 {
    257     printf("			哈夫曼编译码系统
    ");
    258     printf("		1--输入权值并初始化数据
    ");
    259     printf("		2--译码
    ");
    260     printf("		3--打印哈夫曼树
    ");
    261     printf("		4--打印哈夫曼编码
    ");
    262     printf("		0--退出
    ");
    263 }
    264 int main()
    265 {
    266     
    267     int n;//参数n,代表输入权值数量 
    268     int i=0,j=0;
    269     FILE *fout;
    270     char save[60];
    271     menu();
    272     int ce=-1; 
    273     while(ce!=0)
    274     {
    275         printf("输入功能选项: "); 
    276         scanf("%d",&ce);
    277         switch(ce) 
    278         {
    279             case 1: {
    280             printf("输入数据数量:");
    281             scanf("%d",&n); 
    282             //输入编码节点数据 
    283             printf("输入各权值
    ");
    284             for(;i<n;++i)
    285             scanf("%d",&Nodes[i].weight);
    286             HuffmanAnswer(n);}break;
    287             case 2:{
    288                 HuffmanDecoding(n);
    289                 break;
    290             }
    291             case 3: {
    292                 printf("输入哈夫曼树保存路径:");
    293                  scanf("%s",save);
    294                  fout=fopen(save,"w");
    295                 printHuffTree(2*n-2,0,fout);
    296                 printf("哈夫曼树打印到文件%s成功!
    ",save);
    297                 break;
    298             }
    299             case 4:{
    300                 PrintHuffCode(n);
    301                 break;
    302             }
    303             default: break;
    304         }
    305     }
    306     return 0;
    307 }
    308 /*
    309 输入数据数量:7
    310 输入各权值
    311 3 7 10 15 20 20 25
    312 1 2  3 4   5  6  7
    313 权值    编码长度        编码
    314   3     4               0110
    315   7     4               0111
    316  10     3               010
    317  15     3               110
    318  20     3               111
    319  20     2               00
    320  25     2               10
    321  
    322  
    323  输入数据数量:7
    324 输入各权值
    325 3 7 10 15 20 20 25
    326 
    327 12
    328     10
    329         5
    330         8
    331             2
    332             7
    333                 0
    334                 1
    335     11
    336         6
    337         9
    338             3
    339             4
    340 
    341 */
  • 相关阅读:
    关于如何使`(a === 1 && a === 2 && a === 3)`返回`true`问题的思考
    选择适合的类型判断方式
    this的指向问题
    MarkDown基础语法记录
    快速掌握vuex状态管理
    自己如何手动实现一个isNaN的方法
    移动端webapp使用flex布局解决底部导航被手机键盘顶起
    swiper文字内容超出一屏的时候如何实现区域滚动不翻页
    css3动画如何实现停止以后停留在最后一帧动画
    检测任意数据类型
  • 原文地址:https://www.cnblogs.com/sytu/p/4492340.html
Copyright © 2011-2022 走看看