怎么实现huffman(哈夫曼编码)以及解码

 一、编码

【题目描述】

给定一篇用于通信的英文电文,统计该电文中每个字符出现的频率,按频率左小右大的方法为这些字符建立哈夫曼(Huffamn)树,并编出每个字符的哈夫曼树码,输出该电文的哈夫曼码译文。

 

【输入】

输入文件huffman.in是一篇用于通信的英文电文。

【输出】

输出文件huffman.out输出该电文的哈夫曼码译文。

 

【输入输出样例1】

huffman.in                             

huffman.out

aaccdddbacbcddddddd

011011000011101001100010001111111

【数据限制】

2<=英文电文字符数<=10000000

统计以上abcd出现的个数。

a:3   b:2    c:4    d:10

构造出哈夫曼树

怎么实现huffman(哈夫曼编码)以及解码

a:011         b:010     c  :00          d:1

下面主要通过两个结构体数组来实现:

struct node1
{ int w, lch, rch, parent;
}ht[2*N0-1+1];

数组下标 1 2 3 4 5 6 7
父节点的数组下标parent 0 0 0 0      
左孩子节点的数组下标lch 0 0 0 0      
右孩子节点的数组下标rch 0 0 0 0      
权值w 3 2 4 10      

-》

数组下标 1 2 3 4 5 6 7
父节点的数组下标parent 5 5 0 0 0    
左孩子节点的数组下标lch 0 0 0 0 2    
右孩子节点的数组下标rch 0 0 0 0 1    
权值w 3 2 4 10 5    

-》.。。。。。。。。

数组下标 1 2 3 4 5 6 7
父节点的数组下标parent 5 5 6 7 6 7 0
左孩子节点的数组下标lch 0 0 0 0 2 5 6
右孩子节点的数组下标rch 0 0 0 0 1 3 4
权值w 3 2 4 10 5 9 19

 

struct node2
{ char ch;//对应的字符abcd
 int start;//编码的起始位置 注意这个编码是倒着的 所以这里用start
 int code[N0];//这个是编码数组
}hc[N0+1];

大概图如下面

怎么实现huffman(哈夫曼编码)以及解码

美工不好啊 大概将就看了啊

下面给出大家想要的程序部分

//#include "stdio.h"

//#include   "string.h " 

#include <iostream>

#include <string>

const int N0=10;

const int N=100;

const int INF=1000000;

struct node1 

{ int w, lch, rch, parent;

}ht[2*N0-1+1];

struct node2

{ char ch;

 int start;

 int code[N0];

}hc[N0+1];

int n,root;//n为叶子的个数

void readData()

{ char ch;

int num[256]={ 0 };

 n=0;

 freopen( "huffman.in", "r", stdin);//读文本文件

 while( (ch=getchar()) != EOF )

  num[ch]++;

 for( int i=0; i<=255; i++ )

 { if( num[i] )

  { n++;

   ht[n].w=num[i];

   hc[n].ch=i;

  }

 }

}

void select1( int t, int *s1, int *s2)//用两个数来记录没有在树上的最小的两个值,从而进一步生成树。

{ int w1,w2;

 w1=w2=INF;

 for( int i=1; i<=t; i++ )

  if( ht[i].parent==0 )

   if( ht[i].w<w1 )

   { w2=w1;

    *s2=*s1;

    w1=ht[i].w;

    *s1=i;

   }

   else if( ht[i].w<w2 )

   { w2=ht[i].w;

    *s2=i;

   }

}





void createHufTreeHuCode()

{ int i, s1, s2;

 int child, parent;

 root=2*n-1;

 for( i=n+1; i<=root; i++)

 { select1(i-1, &s1, &s2 );

  ht[i].w=ht[s1].w+ht[s2].w;

  ht[i].lch=s1;

  ht[i].rch=s2;

  ht[s1].parent=ht[s2].parent=i;

 }

 for(  i=1; i<=n; i++)

 { child=i;

  while( child != root )

  { parent=ht[child].parent;

   if( ht[parent].lch==child )

    hc[i].code[hc[i].start++]=0;

   else 

    hc[i].code[hc[i].start++]=1;

   child=parent;

  }

 }



}

void txt2code()

{

 int i,j,m;

 char ch1[N+1]={0};

 freopen( "huffman.in", "r", stdin);

 for (int k=1;k<N+1;k++)

 {

  scanf("%c",&ch1[k]);

 }

 for( j=1,i=1; i<=N; i++)

 { if (ch1[i]==0)

  {

   break;

  }

  while (ch1[i]!=hc[j].ch)

  {

   if (hc[j].ch==0)

   {continue;

   }

   j++;

  }

  for( m=hc[j].start-1; m>=0; m--)

   printf("%d", hc[j].code[m]);

  j=1;

 }

}





int main()

{ 

 readData();

 createHufTreeHuCode();

 freopen("huffman.out", "w", stdout);

 txt2code();

 return 0;

}



二、译码

【题目描述】

给定2个输入文件,第1个输入文件是用于通信的英文电文,统计该电文中每个字符出现的频率,按频率左小右大的方法为这些字符建立哈夫曼(Huffamn)树,并编出每个字符的哈夫曼树码;第2个输入文件是已经按第1个输入文件的英文电文编好的哈夫曼码,输出该哈夫曼码的对应的英文电文。

 

【输入】

第1个输入文件为huffman.in是用于通信的英文电文, 第2个输入文件codeToTxt.in是已经按第1个输入文件编好的哈夫曼码。

【输出】

输出文件codeToTxt.out输出codeToTxt.in文件内容的英文电文。

 

【输入输出样例1】

huffman.in                            

codeToTxt.in

codeToTxt.out

aaccdddbacbcddddddd

011111011000011101001100010001111

adddaccdddbacbcdddd

【数据限制】

2<=英文电文字符数<=10000000


 

#include <iostream>

#include <string>

const int N0=10;

const int N=100;

const int INF=1000000;

struct node1 

{ int w, lch, rch, parent;

}ht[2*N0-1+1];

struct node2

{ char ch;

 int start;

 int code[N0];

}hc[N0+1];

int n,root,num[256];

void readData()

{ char ch;



 n=0;

 freopen( "huffman.in", "r", stdin);

 while( (ch=getchar()) != EOF )

  num[ch]++;//同时得到了两个东西,一个是字符,一个是个数

 for( int i=0; i<=255; i++ )

 { if( num[i] )

  { n++;

   ht[n].w=num[i];//个数

   hc[n].ch=i;//字符

  }

 }

}

void select1( int t, int *s1, int *s2)

{ int w1,w2;

 w1=w2=INF;

 for( int i=1; i<=t; i++ )

  if( ht[i].parent==0 )

   if( ht[i].w<w1 )

   { w2=w1;

    *s2=*s1;

    w1=ht[i].w;

    *s1=i;

   }

   else if( ht[i].w<w2 )

   { w2=ht[i].w;

    *s2=i;

   }

}

void createHufTreeHuCode()

{ int i, s1, s2;

 int child, parent;

 root=2*n-1;

 for( i=n+1; i<=root; i++)

 { select1( i-1, &s1, &s2 );

  ht[i].w=ht[s1].w+ht[s2].w;

  ht[i].lch=s1;

  ht[i].rch=s2;

  ht[s1].parent=ht[s2].parent=i;

 }

 for(  i=1; i<=n; i++)

 { child=i;

  while( child != root )

  { parent=ht[child].parent;

   if( ht[parent].lch==child )

    hc[i].code[hc[i].start++]=0;

   else 

    hc[i].code[hc[i].start++]=1;

   child=parent;

  }

 }



}





void code2txt()

{ char ch=0;

int i=root;

 freopen( "codeToTxt.in", "r", stdin);

 freopen("codeToTxt.out", "w", stdout);

 while( (ch=getchar()) != EOF )

 {

 

   if(ht[i].lch&&ht[i].rch)

   {if(ch=='0')

    i=ht[i].lch;

   else

    i=ht[i].rch;

   }

   if(ht[i].lch==0&&ht[i].rch==0)

   { printf("%c",hc[i].ch);

    i=root;

   }

    

 }

}





int main()

{ readData();

 createHufTreeHuCode();

 code2txt();

 return 0;

}




 

你可能感兴趣的:(Huffman)