zoukankan      html  css  js  c++  java
  • 哈弗曼编码和译码.cpp

    <span style="color:#6600cc;">#include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    
    
    typedef struct{
         char a;//记录对应字符
         int weight;//权值
         int parent,lchild,rchild;
    }HTNode,*HuffmanTree;
    
    typedef char * *HuffmanCode;//动态分配数组存储哈夫曼编码表
    
    void Select(HuffmanTree HT,int m,int *s1)//选择双亲节点为0且权值最小的节点
    {int i,j,k,h,a,b;
        for(a=1;a<=m;a++)
            if(HT[a].parent==0)
                 break;
        i=a;k=a;
     for(;i<=m;i++)
        if(HT[i].weight<HT[k].weight&&HT[i].parent==0)
               k=i;
        *s1=k;
    }
    
    //求哈夫曼编码
    void HuffmanCoding(HuffmanTree *HT,HuffmanCode *HC,int *w,char *s,int n)
    {
     int m,i,start,s1,s2,c,f;
     char *cd;
     HuffmanTree p;
     if(n<=1) return;
     m=2*n-1;
     *HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));
     for(i=1;i<=n;i++,w++,s++)
      {(*HT)[i].weight=*w;//叶子节点的权值不变
      (*HT)[i].a=*s;
      (*HT)[i].parent=0,(*HT)[i].lchild=0,(*HT)[i].rchild=0;}
        for(i=n+1;i<=m;i++)
            (*HT)[i].parent=0;//parent初始化
     for(i=n+1;i<=m;++i){//建哈夫曼树
      Select(*HT,i-1,&s1);(*HT)[s1].parent=i;
            Select(*HT,i-1,&s2);/*选择parent为0且权值最小的两个节
            点分别作为s1和s2*/
      (*HT)[s2].parent=i;
      (*HT)[i].lchild=s1;(*HT)[i].rchild=s2;(*HT)[i].a='0';
      (*HT)[i].weight=(*HT)[s1].weight+(*HT)[s2].weight;
     }
     //从叶子到根逆向求每个字符的哈夫曼编码
     (*HC)=(HuffmanCode)malloc((n+1)*sizeof(char *));/*分配n个
     字符编码的头指针向量*/
     cd=(char *)malloc(n*sizeof(char));//分配求编码的工作区间
     cd[n-1]='';//编码结束符
     for(i=1;i<=n;i++){//逐个字符求哈夫曼编码
      start=n-1;//编码结束符位置
      for(c=i,f=(*HT)[i].parent;f!=0;c=f,f=(*HT)[f].parent)/*从叶
      子到根逆向求编码*/
       if((*HT)[f].lchild==c) cd[--start]='0';
            else cd[--start]='1';
     (*HC)[i]=(char *)malloc((n-start)*sizeof(char));/*为第i
     个字符编码分配空间*/
     strcpy((*HC)[i],&cd[start]);//从cd复制编码到HC
     }
    }
    
    //解码
    void HUffmanDising(HuffmanTree HT,int n){
      FILE *fp3,*fp4;HuffmanTree p;
      int c,m;char b;
      p=HT;m=2*n-1;*p=HT[m];
      fp3=fopen("File3.txt","r");
      fp4=fopen("File4.txt","w");
      if(fp3!=NULL)
     {fscanf(fp3,"%c",&b);/*读入一个字符,如果为‘0’遍历左子树,
        为‘1’遍历右子树,遇到叶子节点输出*/
      while(!feof(fp3)){
               if(b=='0'){
                    if((*p).a=='0')
                    c=(*p).lchild,(*p)=HT[c];//指向左孩子
                   }
                if(b=='1'){
                    if((*p).a=='0')
                     c=(*p).rchild,(*p)=HT[c];//指向右孩子
                   }
                if((*p).a!='0')  fprintf(fp4,"%c",(*p).a),//叶子节点输出
                (*p)=HT[m];//指向根结点
                if(!feof(fp3)) fscanf(fp3,"%c",&b);
     }
      }
       fclose(fp4);fclose(fp3);
    }
    
    void PrintfBitree(HuffmanTree *HT,HuffmanCode *HC,int n)
    {int i,j=1,m=n*2-1;
     printf("序号   字符   权值   双亲   左孩子    右孩子  哈夫曼码
    ");
      for(i=1;i<=m;i++,j++)
        {printf(" %02d     %c      %2d     %2d    %2d        %2d",i,(*HT)[i].a,(*HT)[i].weight,(*HT)[i].parent,(*HT)[i].lchild,(*HT)[i].rchild);
        if(j<=n) printf("       %s ",(*HC)[j]);
        printf("
    ");}
    }
    
    int main()
    {   int a[258],n,c[100],i,j,k,z;char e;char m[100],b;
        HuffmanTree HT;HuffmanCode HC;
     FILE *fp1,*fp2,*fp3,*fp4;
     for(i=0;i<=256;i++)
       a[i]=0;//读入一个字符,在数组a中的位置由其ASCII吗决定
        for(i=0;i<100;i++)
             c[i]=0;//记录每一个字符的权值
     fp1=fopen("File1.txt","r");
     if(fp1!=NULL)
     {
      while(!feof(fp1)){
       fscanf(fp1,"%c",&e);
      if(!feof(fp1)) a[(int)e]++;//统计出现次数
      }
     }
     fclose(fp1);
     for(i=0,j=0;i<=256;i++)
       if(a[i]!=0)
       c[j++]=a[i],m[j-1]=(char)i;//将字符存到数组m中
     HuffmanCoding(&HT,&HC,c,m,j);
     fp1=fopen("File1.txt","r");
     fp2=fopen("File2.txt","w");
     fp3=fopen("File3.txt","w+");
     if(fp1!=NULL)//在文件二语三中输出文件一中内容所对应的哈夫曼吗
     {
      while(!feof(fp1)){
       fscanf(fp1,"%c",&e);
       if(feof(fp1)) break;
           for(i=0;i<j;i++)
              if(m[i]==e) break;
              fprintf(fp2,"%s",HC[i+1]);
               fprintf(fp3,"%s",HC[i+1]);
      }
     }
     fclose(fp1);
     fclose(fp2);
     fclose(fp3);
     PrintfBitree(&HT,&HC,j);//输出相关信息
        HUffmanDising(HT,j);//解码函数
    }
    
     
    </span>


     

  • 相关阅读:
    ios中,在SearchBar里面搜索内容,可根据内容来查找所需的信息资源,可获得SearchBar中的内容
    TableViewCell,TableView,UITableViewCell
    iOS-多线程 ,整理集锦,多种线程的创建
    从服务器获取的 数值,进行值传递,不同的文件夹之间的调用。
    Principle 安装步骤
    Principle: 做动效,选对软件很重要 --- 转载自简书
    ios 给图片添加水印
    symbol(s) not found for architecture x86_64 之 linker command failed with exit code 1 (use -v to see invocation)解决方案排查
    IOS 本地通知推送消息
    【ios 7】 之后的设置系统的状态栏隐藏的方法分享
  • 原文地址:https://www.cnblogs.com/codeyuan/p/4254547.html
Copyright © 2011-2022 走看看