【问题描述】
利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。但是,这要求发送端通过一个编码系统对数据进行编码,在接受端将传来的数据进行译码。试为这样的信息收发站写一个哈夫曼编码/译码系统。
【基本要求】
本系统应实现以下功能:(功能1~3必做,4为选做,请课后自行完成)
(1) 初始化:字符集(字母a~z,空格)共27个字符,以及其权值。建立哈夫曼树。并建立各个字符的哈夫曼编码。
(2) 打印字符集的哈夫曼编码。
(3) 编码:从终端读入字符串,实现该字符串的编码。
(4) 译码:实现刚才生成的哈夫曼编码还原为字符串。(选做)#include <iostream>
#include <string.h>
using namespace std;
#define N 50 /*叶子结点数*/
#define M 2*N-1 /*树中结点总数*/
typedef struct
{
char data; /*结点值*/
int weight; /*权重*/
int parent; /*双亲结点*/
int lchild; /*左孩子结点*/
int rchild; /*右孩子结点*/
} HTNode;
typedef struct
{
char cd[N]; /*存放哈夫曼码*/
int start;
} HCode;
void CreateHT(HTNode ht[],int n){ /*创建哈夫曼树*/
int i, j, k, lnode, rnode;
double min1, min2;
for(i = 0 ; i < 2*n-1 ; i++)
ht[i].parent = ht[i].lchild = ht[i].rchild = -1;
for(i = n ; i < 2*n-1 ; i++){
min1 = min2 = 32767;
lnode = rnode = -1;
for(k = 0; k <= i - 1 ; k++)
if(ht[k].parent == -1){
if( ht[k].weight < min1){
min2 = min1; rnode = lnode;
min1 = ht[k].weight; lnode = k;
}
else if(ht[k].weight < min2){
min2 = ht[k].weight; rnode = k;
}
}
ht[i].weight = ht[lnode].weight + ht[rnode].weight;
ht[i].lchild = lnode; ht[i].rchild = rnode;
ht[lnode].parent = i; ht[rnode].parent = i;
}
}
void CreateHCode(HTNode ht[],HCode hcd[],int n){ /*创建哈夫曼编码*/
int i, f, c;
HCode hc;
for(i = 0; i < n; i++){
hc.start = n; c = i;
f = ht[i].parent;
while(f != -1){
if(ht[f].lchild == c)
hc.cd[hc.start--] = '0';
else
hc.cd[hc.start--] = '1';
c = f; f=ht[f].parent;
}
hc.start++;
hcd[i] = hc;
}
}
void DispHCode(HTNode ht[],HCode hcd[],int n){ /*显示各个字符的哈夫曼编码*/
int i,k;
int sum=0,m=0,j;
cout<<"该字符集的哈夫曼编码如下: "<<endl;
for(i=0;i<n;i++){
j=0;
cout<<ht[i].data<<" ";
for(k=hcd[i].start;k<=n;k++){
cout<<hcd[i].cd[k];
}
printf("\n");
}
}
void Encode(char *s,HTNode ht[],HCode hcd[],int n){ /*显示字符串s的哈夫曼编码*/
int i, j, k;
for(i = 0; s[i] != '\0'; i++)
cout<<s[i];
cout<<"的哈夫曼编码是: "<<endl;
i = j =0;
while(s[j] != '\0'){
if(s[j] == ht[i].data){
for(k = hcd[i].start; k <= n; k++)
cout<<hcd[i].cd[k];
j++;
i = 0;
}
else
i++;
}
cout<<endl;
}
int main(){
int n = 27,i;
char s[100];
char str[]={' ','a','b','c','d','e','f','g','h','i','j','k','l','m','n',
'o','p','q','r','s','t','u','v','w','x','y','z'}; /*字符集*/
int fnum[]={186,64,13,22,32,103,21,15,47,57,1,5,32,20,57,
63,15,1,48,51,80,23,8,18,1,16,1}; /*字符集对应的权值*/
HTNode ht[M];
HCode hcd[N];
for (i = 0 ; i < n ; i++){
ht[i].data = str[i];
ht[i].weight = fnum[i];
}
CreateHT(ht,n);
CreateHCode(ht,hcd,n);
DispHCode(ht,hcd,n);
cout<<endl<<endl<<"请输入字符串: ";gets(s);
Encode(s,ht,hcd,n);
return 0;
}
#include <iostream>
#include <string.h>
using namespace std;
#define N 50 /*叶子结点数*/
#define M 2*N-1 /*树中结点总数*/
typedef struct
{
char data; /*结点值*/
int weight; /*权重*/
int parent; /*双亲结点*/
int lchild; /*左孩子结点*/
int rchild; /*右孩子结点*/
} HTNode;
typedef struct
{
char cd[N]; /*存放哈夫曼码*/
int start;
} HCode;
void CreateHT(HTNode ht[],int n){ /*创建哈夫曼树*/
int i, j, k, lnode, rnode;
double min1, min2;
for(i = 0 ; i < 2*n-1 ; i++)
ht[i].parent = ht[i].lchild = ht[i].rchild = -1;
for(i = n ; i < 2*n-1 ; i++){
min1 = min2 = 32767;
lnode = rnode = -1;
for(k = 0; k <= i - 1 ; k++)
if(ht[k].parent == -1){
if( ht[k].weight < min1){
min2 = min1; rnode = lnode;
min1 = ht[k].weight; lnode = k;
}
else if(ht[k].weight < min2){
min2 = ht[k].weight; rnode = k;
}
}
ht[i].weight = ht[lnode].weight + ht[rnode].weight;
ht[i].lchild = lnode; ht[i].rchild = rnode;
ht[lnode].parent = i; ht[rnode].parent = i;
}
}
void CreateHCode(HTNode ht[],HCode hcd[],int n){ /*创建哈夫曼编码*/
int i, f, c;
HCode hc;
for(i = 0; i < n; i++){
hc.start = n; c = i;
f = ht[i].parent;
while(f != -1){
if(ht[f].lchild == c)
hc.cd[hc.start--] = '0';
else
hc.cd[hc.start--] = '1';
c = f; f=ht[f].parent;
}
hc.start++;
hcd[i] = hc;
}
}
void DispHCode(HTNode ht[],HCode hcd[],int n){ /*显示各个字符的哈夫曼编码*/
int i,k;
int sum=0,m=0,j;
cout<<"该字符集的哈夫曼编码如下: "<<endl;
for(i=0;i<n;i++){
j=0;
cout<<ht[i].data<<" ";
for(k=hcd[i].start;k<=n;k++){
cout<<hcd[i].cd[k];
}
printf("\n");
}
}
void Encode(char *s,HTNode ht[],HCode hcd[],int n){ /*显示字符串s的哈夫曼编码*/
int i, j, k;
for(i = 0; s[i] != '\0'; i++)
cout<<s[i];
cout<<"的哈夫曼编码是: "<<endl;
i = j =0;
while(s[j] != '\0'){
if(s[j] == ht[i].data){
for(k = hcd[i].start; k <= n; k++)
cout<<hcd[i].cd[k];
j++;
i = 0;
}
else
i++;
}
cout<<endl;
}
int main(){
int n = 27,i;
char s[100];
char str[]={' ','a','b','c','d','e','f','g','h','i','j','k','l','m','n',
'o','p','q','r','s','t','u','v','w','x','y','z'}; /*字符集*/
int fnum[]={186,64,13,22,32,103,21,15,47,57,1,5,32,20,57,
63,15,1,48,51,80,23,8,18,1,16,1}; /*字符集对应的权值*/
HTNode ht[M];
HCode hcd[N];
for (i = 0 ; i < n ; i++){
ht[i].data = str[i];
ht[i].weight = fnum[i];
}
CreateHT(ht,n);
CreateHCode(ht,hcd,n);
DispHCode(ht,hcd,n);
cout<<endl<<endl<<"请输入字符串: ";gets(s);
Encode(s,ht,hcd,n);
return 0;
}