⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 huffman.c

📁 Huffman 编解码源程序 VC语言开发
💻 C
📖 第 1 页 / 共 2 页
字号:

          fputc(temp,ofp);

          if(buffer[i][j]==-1)break;

          ++i;

     }

}

/**********************以下是解压缩算法************************/

void decompress(FILE *ifp,FILE *ofp)

{

     int i=0;

     signed ArraySize=0;

     RateTabNode *head;

     CodeNode *codehead,*codetmp;//存储编码的数组首地址]

     OFinal *ofinalhead;

     HuffmanTree *root;//树根

     LeafNode *leafhead;//存储叶子结点的地址,利于编码

     char buffer[MaxSize][8];

 

     buf_init(buffer,MaxSize);

     fread(&ArraySize,sizeof(unsigned),1,ifp);//读字符种类数

     

     codehead=(CodeNode *)malloc(ArraySize*sizeof(CodeNode));

     codetmp=(CodeNode *)malloc(ArraySize*sizeof(CodeNode));

     ofinalhead=(OFinal *)malloc(ArraySize*sizeof(OFinal));

     fread(ofinalhead,sizeof(OFinal),ArraySize,ifp);//读字符和权

 

     head=RebuildLink(ofinalhead,ArraySize);

         

     root=HTCreate(head);//创建Huffman树,返回根结点

         

     leafhead=(LeafNode *)malloc(ArraySize*sizeof(LeafNode));

     codehead=(CodeNode *)malloc(ArraySize*sizeof(CodeNode));

         

     for(i=0;i<ArraySize;++i)

     {

         int j=0;

         for(j=0;j<CodeMaxLen;++j)

              codetmp[i].code[j]='#';

     }

     //初始化编码表全部为'#'

     FindLeaf(root,leafhead,ArraySize);//找出所有叶子结点,记录地址

     HFCoding(leafhead,codetmp,ArraySize);//从叶子到根,从下向上进行编码

/*******以下循环去除#在编码前,以便字符串的匹配********/

     for(i=0;i<ArraySize;++i)

     {

         int j=0,k=0;

         codehead[i].ch=codetmp[i].ch;

         for(j=0,k=0;j<CodeMaxLen;++j)

         {

              if(codetmp[i].code[j]!='#')

              {

                   codehead[i].code[k]=codetmp[i].code[j];

                   ++k;

              }

         }

     }

     free(codetmp);

     while(!feof(ifp))

     {

         deWbuffer(ifp,buffer,MaxSize);

         deRbuffer(ofp,codehead,ArraySize,buffer,MaxSize);

     }

}

RateTabNode *RebuildLink(OFinal *ofinalhead,int ArraySize)//恢复双链表结构

{

     RateTabNode *head,*p,*q;

     int i=0;

 

     q=(RateTabNode *)malloc(sizeof(RateTabNode));

     head=p=q;

     q->next=NULL;

     head->pre=NULL;

     head->LChild=head->RChild=NULL;

 

     for(i=0;i<ArraySize;++i)

     {

         p->ch=ofinalhead[i].ch;

         p->weight=ofinalhead[i].weight;

        if(i==ArraySize-1)break;

         q=(RateTabNode *)malloc(sizeof(RateTabNode));

         p->next=q;

         q->pre=p;

         p=q;

         p->next=NULL;

         p->LChild=p->RChild=NULL;

     }

     return head;

}

void deWbuffer(FILE *ifp,char (*buffer)[8],int size)

{

     char temp;

     int i=0;

 

     buf_init(buffer,MaxSize);

     while(i<size-1&&!feof(ifp))

     {

         int j=0;

         temp=fgetc(ifp);

        if(feof(ifp))return;

         for(j=0;j<8;++j)

              buffer[i][j]=((temp>>(7-j))&1)+48;//写入的是数字,注意转换为字符'1'

         ++i;

     }

}

char CodeMatch(CodeNode *codehead,int ArraySize,char *ch)//在编码中找当前字符串是否是编码,是则返回该编码对应字符,否则返回'\0'

{

     int i;

     for(i=0;i<ArraySize;++i)

         if(strcmp(codehead[i].code,ch)==0)

              return codehead[i].ch;

     return '\0';

}

void deRbuffer(FILE *ofp,CodeNode *codehead,int ArraySize,char (*buffer)[8],int size)//解码,还原文件

{

     int i=0;

     char temp[CodeMaxLen];

     char ch;

    temp[0]='\0';

 

     while(*(*buffer+i)!=-1)//读一个字符

     {

         chstract(temp,*(*buffer+i));//将字符加到字符串temp后

         if((ch=CodeMatch(codehead,ArraySize,temp))!='\0')//匹配则解码,否则字符串继续变长

         {

              fputc(ch,ofp);

              temp[0]='\0';

         }

         ++i;

     }

}

void chstract(char *temp,char ch)//把一个字符加到当前字符串末尾

{

     int i;

     for(i=0;i<CodeMaxLen;++i)

     {

         if(temp[i]=='\0')

         {

              temp[i]=ch;

              temp[i+1]='\0';

              return;

         }

     }

     

}

 

/***************共用算法****************/

HuffmanTree *HTCreate(RateTabNode *head)//双链表形式创建Huffman树

{

     HuffmanTree *p1,*p2,*root;

    RateTabNode *temp,*p;

 

     root=(HuffmanTree *)malloc(sizeof(HuffmanTree));

     //printf("%d\n",SizeAssure(head));

    if(SizeAssure(head)==2)//当只生剩下两个元素,直接将这两棵树作为子树,返回总根结点地址

     {

         root->ch='\0';

         root->LChild=head;

         head->parent=root;

         root->RChild=head->next;

         root->weight=head->weight+head->next->weight;

         head->next->parent=root;

         head=root;

        head->parent=NULL;

 

         return head;

     }

     else

     {

       for(p=temp=head;p!=NULL;p=p->next)//找权最小的结点

       {

         if(temp->weight>p->weight)

              temp=p;

         

       }

       p1=temp;

       /****记下最小结点的地址,将它从链表中移除(分三种情况,头、尾和中间)***/

       if(p1->pre==NULL)//表头

       {

           head=head->next;

           head->pre=NULL;

       }

       else if(p1->next==NULL)//表尾

       {

           p1->pre->next=NULL;

       }

       else

       {

           p1->pre->next=p1->next;

           p1->next->pre=p1->pre;

           

       }//中间   

       p1->next=p1->pre=NULL;

       /*********寻找次小权结点,过程同上面完全相同,找去掉最小后的最小,即次小**********/

       for(temp=p=head;p!=NULL;p=p->next)

       {

         if(temp->weight>p->weight)

              temp=p;

       }

       p2=temp;

       if(p2->pre==NULL)

       {

           head=head->next;

           head->pre=NULL;

       }

       else if(p2->next==NULL)

       {

           p2->pre->next=NULL;

       }

       else

       {

           p2->pre->next=p2->next;

           p2->next->pre=p2->pre;

           

       }

       //取次小值

      p2->next=p2->pre=NULL;

       //printf("%d\n",SizeAssure(head));getch();

       /*********将两个最小值建立一棵子树,并将它们的根结点插入双链表**********/

       root->LChild=p1;

       root->RChild=p2;

       p1->parent=root;

       p2->parent=root;

     

       root->ch='\0';

       root->weight=p1->weight+p2->weight;

       root->next=head;

       head->pre=root;

       head=root;

       head->pre=NULL;

 

       head=HTCreate(head);//递归,直到剩两个结点在双链表中

     }

	 return head;

}

 

void FindLeaf(RateTabNode *head,LeafNode *leafhead,int size)//递归查找叶子,记下地址到数组

{

     static int num=0;

     if(head->LChild==NULL&&head->RChild==NULL&&num<size)

     {

         leafhead[num].ch=head->ch;

         leafhead[num].leaf=head;

         ++num;

         return;

     }

     if(head==NULL)return;

     

     FindLeaf(head->LChild,leafhead,size);

     FindLeaf(head->RChild,leafhead,size);

     

}

void HFCoding(LeafNode *leafhead,CodeNode *codehead,int size)//自下向上编码,左右

{

     int i=0,j=CodeMaxLen;

      LeafNode *leaftmp=leafhead;

      while(i<size)

      {

          j=CodeMaxLen;

          codehead[i].ch=leaftmp[i].ch;

          codehead[i].code[--j]='\0';

          while(leaftmp[i].leaf->parent!=NULL&&j>=0)

          {

               if(leaftmp[i].leaf->parent->LChild==leaftmp[i].leaf)

                    codehead[i].code[--j]='0';

               if(leaftmp[i].leaf->parent->RChild==leaftmp[i].leaf)

                    codehead[i].code[--j]='1';

               leaftmp[i].leaf=leaftmp[i].leaf->parent;//向上

          }

          ++i;

      }

}

void buf_init(char (*buffer)[8],int size)//缓冲初始化

{

     int i,j;

     for(i=0;i<size;++i)

         for(j=0;j<8;++j)

              buffer[i][j]=-1;

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -