【題目描述】
給定一篇用於通信的英文電文,統計該電文中每個字符出現的頻率,按頻率左小右大的方法爲這些字符建立哈夫曼(Huffamn)樹,並編出每個字符的哈夫曼樹碼,輸出該電文的哈夫曼碼譯文。
【輸入】
輸入文件huffman.in是一篇用於通信的英文電文。
【輸出】
輸出文件huffman.out輸出該電文的哈夫曼碼譯文。
【輸入輸出樣例1】
huffman.in |
huffman.out |
aaccdddbacbcddddddd |
011011000011101001100010001111111 |
【數據限制】
2<=英文電文字符數<=10000000
統計以上abcd出現的個數。
a:3 b:2 c:4 d:10
構造出哈夫曼樹
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];
大概圖如下面
美工不好啊 大概將就看了啊
下面給出大家想要的程序部分
//#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;
}