zoukankan      html  css  js  c++  java
  • 哈夫曼编码器

    # include <stdio.h>
    # include <stdlib.h>
    # include <string.h>
    # include <limits.h>
    # include <fstream>
    # include <iostream>
    using namespace std;
    # define  maxsize 100
     
    //将信息转化为哈夫曼码 
    //康玉健
    //17041114 
    typedef struct 
    {
        int order;//序号 
        char letter;//字母 
        int count;//出现的次数 
        
    }LET;//字母 
    typedef struct
    {
        int weight;
        int parent;
        int left_child;
        int right_child;
        char elem;
        
    }HTNode,*HuffmanTree;//定义哈弗曼树 
    typedef struct
    {
        char letter;
        char *code;
    }CODE;//哈夫曼表 
    typedef char**HuffmanCode;
    void creat_HuffmanTree(HuffmanTree &HT,int n,LET *letter);//创建哈弗曼树
    void HuffmanTree_select(HuffmanTree &HT,int num_node,int &s1,int &s2);//进行选择 
    LET* statis_letter(char *data);//统计字母个数 
    int statis_letternum(LET* letter);//统计含有字符多少个 
    //LET *outcome(LET*letters);//返回最终的数组
    void Huffman_code(HuffmanTree &HT,HuffmanCode &HC,int n);//创建哈夫曼编码表
    void print_HuffmanCode(HuffmanCode &HC,LET *letter,int n);//打印哈夫曼表 
    char* output_HuffmanCode(HuffmanCode &HC,char *data,int n,LET*letter);//输出哈夫曼编码 
    //void resolve_HuffmanCode(HuffmanTree &HT,HuffmanCode HC,char *code)//解哈夫曼编码 
    int  Root_Tree(HuffmanTree &HT,int n);   //得到哈夫曼树的根 
    void resolve_HuffmanCode(HuffmanTree &HT,LET*letter2,char *code,int n);
    LET* enter_weight(int len,LET* letter);//输入权值 
    void output_huffman_to_file(HuffmanTree &HT,int len);//将哈夫曼树输入到文件中 
    void Init(int len,LET* letter);//初始化功能 
    HuffmanTree En_code(int len,LET* letter);//编码到一个文件中 
    void De_code(HuffmanTree &HT,LET*letter2,char *code,int n);//译码部分
    void print_code(void); 
    void print_Tree(HuffmanTree &HT,int len);
    
    int main(void)
    {
        int flag=0;
        int returnmenu;
        int choice;
        printf("****************************************\n");
        printf("*              哈夫曼编码器            *\n");
        printf("*                  版本1.0             *\n");
        printf("*                                      *\n");
        printf("*                                      *\n");
        printf("*                                      *\n");
        printf("*                                      *\n");
        system("pause");
        system("cls");
        HuffmanTree HT=NULL; 
        char data[maxsize];
        char code[maxsize];
        printf("请输入一个您要进行编码的字符串:(长度小于100)\n");
        gets(data);
        LET*letter=statis_letter(data);//统计字符串中各个字母出现的频率 
        int len=statis_letternum(letter);
        LET*letter2= enter_weight(len,letter);
        do{
        
        system("cls");
        printf("*         【1】初始化                  *\n");
        printf("*         【2】编码                    *\n");
        printf("*         【3】译码                    *\n");
        printf("*         【4】印代码文件              *\n");
        printf("*         【5】打印哈夫曼树            *\n");
        printf("请输入您的选择:\n");
        scanf("%d",&choice);
        
        if(choice==1)
        {
        Init(len,letter2);
        }
        else if(choice==2)
        {
        
        HT=En_code(len,letter2);
        }
        else if(choice==3)
        {
        FILE* fp=fopen("编完码的结果.txt","r");
        if(fp==NULL)
        {
            printf("文件打不开!\n");
        }
        else
        {
            fscanf(fp,"%s",&code);
            fclose(fp);
            De_code(HT,letter2,code,len);
        }
        
    }
    else if(choice==4)
    { 
    
        print_code();
    }
    else if(choice==5)
    {
      
        print_Tree(HT,len);
    }
    else
    {
        printf("输入错误!\n");
    }
    printf("是否返回主菜单:\n");
    printf("【1】是,【2】否\n");
    scanf("%d",&returnmenu);
    }
    while(returnmenu==1);
    
    }
    void creat_HuffmanTree(HuffmanTree &HT,int n,LET*letters)//创建哈夫曼树 
    {
    
        int m;
        int i;
        int j;
        int s1,s2; 
        if(n<=1)
        return ;
        m=2*n-1;
        HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));
        HT[0].elem='#';
        HT[0].left_child=0;
        HT[0].right_child=0;
        HT[0].parent=0;
        HT[0].weight=0;
        for(i=1;i<=m;i++)
        {
            HT[i].elem='#';
            HT[i].parent=0;
            HT[i].left_child=0;
            HT[i].right_child=0;    
        }
        //依次输入%d个节点的位权值
        for(i=1;i<=n;i++)
        {
          HT[i].weight=letters[i-1].count;
          HT[i].elem=letters[i-1].letter;
        }
        //从1-i-1选择最小的两个节点并将权值返回给s1。s2
        for(i=n+1;i<=m;i++)
        {
            HuffmanTree_select(HT,i-1,s1,s2);
            HT[s1].parent=i;
            HT[s2].parent=i;
            HT[i].left_child=s1;
            HT[i].right_child=s2;
            HT[i].weight=HT[s1].weight+HT[s2].weight;
        }
         
        
     } 
     void HuffmanTree_select(HuffmanTree &HT,int num_node,int &s1,int &s2)//选择最小权值的下标 
     {
         int i;
        s1 = s2 = 0; 
        int min1 = INT_MAX;//最小值,INT_MAX在<limits.h>中定义的
        int min2 = INT_MAX;//次小值
     
        for ( i = 1; i <=num_node; ++i )
        {
        if ( HT[i].parent == 0 )
        {//筛选没有父节点的最小和次小权值下标
            if ( HT[i].weight < min1 )
            {//如果比最小值小
            min2 = min1;
             s2 = s1;
            min1 = HT[i].weight;
            s1 = i;
            }
            else if ( (HT[i].weight >= min1) && (HT[i].weight < min2) )
               {//如果大于等于最小值,且小于次小值
            min2 = HT[i].weight;
             s2 = i;
            }
            else
            {//如果大于次小值,则什么都不做
            ;
            }
        }
        }
    
    
     }
     LET* statis_letter(char *data)// 统计多少字符串之中各个字母数目 
     {
         int i,j;
         int len;
         int count=0;
        
        LET* letter=(LET*)malloc(26*sizeof(LET));
    
        for(i=0;i<26;i++)//依次把26个字母放到字母结构体数组之中 
        {
            letter[i].order=i;
            letter[i].letter='A'+i;
            letter[i].count=0;
        }
        
        for(i=0;i<strlen(data);i++)
        {
            for(j=0;j<26;j++)
            {
                if(letter[j].letter==data[i])
                {
                    letter[j].count++;
                }
            }
           
        }
        
        return letter;
         
         
      } 
      int statis_letternum(LET* letter)//统计字母的个数 
      {
          int i;
          int count=0;
          for(i=0;i<26;i++)
          {
              if(letter[i].count!=0)
              {
                  count++;
              }
        
          }
          return count;
       } 
    /*LET *outcome(LET*letters)//把所有返回一个有全部字母的数组 
    {
        int i;
        int counts=0;
        int len=statis_letternum(letters);
        LET *outcome=(LET*)malloc(len*sizeof(LET));
        for(i=0;i<26;i++)
        {
            if (letters[i].count!=0)
            {
                outcome[counts].letter=letters[i].letter;
                outcome[counts].order=letters[i].count;
                outcome[counts].order=letters[i].order;
                counts++;
            }
        }
        printf("count=%d",counts);
        return outcome;
    }*/
    void Huffman_code(HuffmanTree &HT,HuffmanCode &HC, int n)//哈夫曼编码树 
    {
        int i;
        int c;
        int start;
        int f;
        
        HC=(HuffmanCode)malloc((n+1)*sizeof(char *));
        
        char *cd=(char*)malloc(n*sizeof(char));
        
        cd[n-1]='\0';
         
        for(i=1;i<=n;++i)
        {
            start=n-1;
            c=i;
            f=HT[i].parent;
            
            while(f!=0)
            {
                --start;
                if(HT[f].left_child==c)
                {
                    cd[start]='0';
                        
                }
                else
                {
                    cd[start]='1';
                    
            }
                c=f;
                f=HT[f].parent;
                HC[i]=(char*)malloc((n-start)*sizeof(char));
                strcpy(HC[i],&cd[start]);
        
             } 
            
            
        
        }
        free(cd);
        
         
     }
     void print_HuffmanCode(HuffmanCode &HC,LET *letter,int n)
     {
         FILE* fp=fopen("编码表.txt","w");
         if(fp==NULL)
         {
             printf("文件打不开呀!兄弟!\n");
         }
         else
         {
         
         int i;
         for(i=0;i<n;i++)
         {
             if(letter[i].count!=0)
             {
             
             fprintf(fp,"字母:"); 
             fprintf(fp,"%c ",letter[i].letter);
             fprintf(fp,"权值:"); 
             fprintf(fp,"%d ",letter[i].count);
             fprintf(fp,"哈夫曼编码为:\n");
             fprintf(fp,"%s",HC[i+1]);
             fprintf(fp,"\n");
         }
             
             
         }
         fclose(fp);
        } 
     }
     char * output_HuffmanCode(HuffmanCode &HC,char *data,int n,LET* letter)
     {
            int i,j;
            CODE *HCode=(CODE*)malloc(n*sizeof(CODE));
            char *output_string=(char*)malloc(maxsize*sizeof(char));
            output_string[0]='\0';
            for(i=0;i<n;i++)
            {
                HCode[i].letter=letter[i].letter;
            }
           for(i=0;i<n;i++)
           {
               HCode[i].code=(char*)malloc(strlen(HC[i+1])*sizeof(char));
               strcpy(HCode[i].code,HC[i+1]);
            } 
            printf("转化为哈夫曼码为:\n");
            for(i=0;i<strlen(data);i++)
            {
                for(j=0;j<n;j++)
                {
                    if(data[i]==HCode[j].letter)
                    {
                        strcat(output_string,HCode[j].code);
                        printf("%s",HCode[j].code);
                    }
                }
            }
            printf("\n");
            printf("传输的哈夫曼编码为:\n");
            puts(output_string);
            FILE* fp=fopen("编完码的结果.txt","w");
            if(fp==NULL)
            {
                printf("读取文件失败!\n");
            }
            else
            {
                for(i=0;i<strlen(output_string);i++)
                {
                if(i+1%50==0)
                {
                    fprintf(fp,"\n");
                }
                fprintf(fp,"%c",output_string[i]);
            }
            }
            fclose(fp);
            return output_string;
        
            
      } 
      int  Root_Tree(HuffmanTree &HT,int n)  //返回哈弗曼树根节点的下标
      {
          int i;
          int m=2*n-1;
          for(i=1;i<=m;i++)
          {
              if(HT[i].parent==0)
              {
                  break;
              }
          }
        return i;
          
       }
    void resolve_HuffmanCode(HuffmanTree &HT,LET*letter2,char *code,int n)
    {
        FILE* fp=fopen("译码的结果.txt","w");
        if(fp==NULL)
        {
            printf("文件打不开,我的朋友!\n");
        }
        else
        {
        
        int root=Root_Tree(HT,n); 
        int i=root;
        int weight; 
        do
        {
            
            if(*code=='0')//如果 
            {
                i=HT[i].left_child;
                
            }
            else if(*code=='1')
            {
               i=HT[i].right_child;
            }
            if(HT[i].left_child==0&&HT[i].right_child==0)//如果到达了叶子节点回到根节点 
            {
                weight=HT[i].weight;
                fprintf(fp,"%c",HT[i].elem);
                 
                i=root;
                
            }
            code++;
    }
    while(*code!='\0');
    fclose(fp);
    }
     } 
    LET* enter_weight(int len,LET* letter)
    {   
        int i;
        int count=0;
        int weight;
        LET*letter2=(LET*)malloc(len*sizeof(LET)); 
        for(i=0;i<26;i++)
        {
            if(letter[i].count!=0)
            {
                printf("请输入%c的权值:\n",letter[i].letter);
                scanf("%d",&weight);
                letter2[count].count=weight;
                letter2[count].order=letter[i].order;
                letter2[count].letter=letter[i].letter;        
                count++;
        }
        }
        return letter2;
    }  
    
    void Init(int len,LET* letter)
    {
        int i;
        int count=0;
        char data[maxsize];
        HuffmanCode HC=NULL;
        HuffmanTree HT=NULL;
        char code[100];
        
        creat_HuffmanTree(HT,len,letter);
        output_huffman_to_file(HT,len);
    
    } 
    
    
    void output_huffman_to_file(HuffmanTree &HT,int len)//打印哈夫曼树 
    {
        char code[100];
        ofstream file;
        file.open("哈夫曼树.txt");
        for(int i=0;i<2*len;i++)
        {
            //file<<i<<" ";
            file<<HT[i].elem<<" ";
            file<<HT[i].weight<<" ";
            file<<HT[i].parent<<" ";
            file<<HT[i].left_child<<" ";
            file<<HT[i].right_child<<" ";
            file<<endl; 
        }
        file.close();
    }  
    HuffmanTree En_code(int len,LET* letter)//读取哈夫曼树并对其进行编码 
    {
        //创建哈夫曼树 
        HuffmanTree HT_new=(HuffmanTree)malloc(2*len*sizeof(HTNode));
        //创建一个新的哈夫曼树
        //从文件中读取哈夫曼树
        char ch1,ch2;
        char elem;
        int weight;
        int parent;
        int left_child;
        int right_child;
        char code[100];
        HuffmanCode HC;
        FILE *fp=fopen("哈夫曼树.txt","r");
    
        for(int i=0;i<2*len;i++)
        {
            fscanf(fp,"%c",&elem);
            fscanf(fp,"%d",&weight);
            fscanf(fp,"%d",&parent);
            fscanf(fp,"%d",&left_child);
            fscanf(fp,"%d",&right_child);
            fscanf(fp,"%c%c",&ch1,&ch2);
            HT_new[i].elem=elem;
            HT_new[i].weight=weight;
            HT_new[i].parent=parent;
            HT_new[i].left_child=left_child;
            HT_new[i].right_child=right_child;
            
        } 
        //file.close();
        fclose(fp);
        for(int i=0;i<2*len;i++)
        {
            cout<<HT_new[i].elem<<" ";
            cout<<HT_new[i].weight<<" ";
            cout<<HT_new[i].parent<<" ";
            cout<<HT_new[i].left_child<<" ";
            cout<<HT_new[i].right_child<<endl; 
        }
        //打开要被编码的文件
        FILE *fp1=fopen("要被编码的数据.txt","r");
        fscanf(fp1,"%s",&code);
        fclose(fp1);
        Huffman_code(HT_new,HC,len);
        output_HuffmanCode(HC,code,len,letter);
        //打印哈夫曼树编码表
        print_HuffmanCode(HC,letter,len); 
        return  HT_new;
        
    }
    void De_code(HuffmanTree &HT,LET*letter2,char *code,int n)
    {
        resolve_HuffmanCode(HT,letter2,code,n);
    }
    void print_code(void)
    {
        char code[maxsize];
        FILE* fp=fopen("译码的结果.txt","r");
        if(fp==NULL)
        {
            printf("打不开文件啊,兄弟!\n");
            exit(-1);
         } 
         else
         {
             fscanf(fp,"%s",&code);
             fclose(fp);
         }
         printf("译码的结果为:\n");
         puts(code);
    }
    void print_Tree(HuffmanTree &HT,int len)
    {
        FILE* fp=fopen("打印哈夫曼树.txt","w");
        if(fp==NULL)
        {
            printf("文件打不开!\n");
            exit(-1);
        }
        else
        {
            for(int i=0;i<2*len;i++)
            {
                fprintf(fp,"序号: ");
                fprintf(fp,"元素: ");
                fprintf(fp,"权值: ");
                fprintf(fp,"父母:  ");
                fprintf(fp,"左孩子: ");
                fprintf(fp,"右孩子:  ");
                fprintf(fp,"\n");
                fprintf(fp,"%d       ",i);
                fprintf(fp,"%c       ",HT[i].elem);
                fprintf(fp,"%d       ",HT[i].weight);
                fprintf(fp,"%d       ",HT[i].parent);
                fprintf(fp,"%d       ",HT[i].left_child);
                fprintf(fp,"%d       ",HT[i].right_child);
                fprintf(fp,"\n");
                 
            }
            fclose(fp);
        }
    }
  • 相关阅读:
    【REST详述及RESTful规范】
    【Vue CLI】从安装到构建项目再到目录结构的说明
    【Webpack】
    【npm】安装、搭建独立项目环境
    【Node.js安装步骤】
    【Vue路由系统详述】
    【Python实现图片验证码】
    【Vue实例生命周期】
    【Vue组件系统】
    Java实现几种常见排序方法
  • 原文地址:https://www.cnblogs.com/mengxiaoleng/p/11181093.html
Copyright © 2011-2022 走看看