题目3
在一个加密应用中,要处理的信息来自下面的字符集,各个字符的相关使用频度如下:
字符空格 A B C D E F G H I J K L M
频度 180 64 13 23 32103 22 15 47 57 1 5 31 20
字符 N O P Q R S T U V W X Y Z
频度 55 63 15 1 48 56 80 25 7 18 2 16 1
现请编写程序你实现如下功能:
(1)运行时,由用户输入来初始化字符集大小和相应用字符。
(2)输入一个要加密的字符串,将其加密。
(3)输出解密字符串。
代码
#include<stdio.h>
#define N 27 //空格+26个大写字母
#define M 2*N-1
#define infinity 32767
struct node //huffman树的结点结构
{
int weight; //结点权值
int prents,lchild,rchild; //双亲,左孩子,右孩子
};
struct codetype //huffman编码结构
{
int start; //起始位置
char bits[N+1]; //存放0,1的数组
};
struct element //字符及其编码的结构
{
char symbol; //字符
struct codetype code; //字符编码
};
struct node tree[M+1]; //n个结点的huffman树
struct element user[N+1],t[100]; //n个结点的huffman编码表,用户编码
int x1,x2;
void sethuftree(); //有关函数声明
void select0(int s);
void sethufcode();
void setcode();
void printtree();
void printhufcode();
void Decrypt();
void Encryptor();
void main() //**********主函数**********
{
sethuftree();
printtree();
sethufcode();
printhufcode();
setcode();
printf("\n\n");
}
void sethuftree() //建立huffuman树
{
int i,treeweight[N]={180,64,13,23,32,103,22,15,47,57,1,5,31,20,55,63,15,1,48,56,80,25,7,18,2,16,1};
char usersymbol[N]={' ','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'};
for(i=1;i<=M;i++) //初始双亲,左,右结点为:0
tree[i].prents=tree[i].lchild=tree[i].rchild=0;
for(i=1;i<=N+1;i++) //初始化27个字符及其权值
{
user[i].symbol=usersymbol[i-1];
tree[i].weight=treeweight[i-1];
}
for(i=N+1;i<=M;i++) //找权值最小的2个结点,组成huffman树
{
select0(i-1); //调用找权值最小的2个结点函数
tree[x1].prents=i;
tree[x2].prents=i;
tree[i].lchild=x1;
tree[i].rchild=x2;
tree[i].weight=tree[x1].weight+tree[x2].weight;
}
}
void select0(int s) //找权值最小的2个结点
{
int i;
float v1,v2;
v1=v2=infinity;
x1=x2=0;
for(i=1;i<=s;i++)
if(tree[i].prents==0)
if(tree[i].weight<v1)
{
v2=v1;
x2=x1;
v1=tree[i].weight;
x1=i;
}
else if(tree[i].weight<v2)
{
v2=tree[i].weight;
x2=i;
}
}
void printtree() //输出huffman树
{
int i;
printf("哈夫曼树为:\n\n");
printf("结点值 权值(频度) 双亲 左孩子 右孩子\n");
for(i=1;i<=N;i++)
printf(" %-8c%-11d%-8d%-8d%d\n",user[i].symbol,tree[i].weight,tree[i].prents,tree[i].lchild,tree[i].rchild);
for(i=N+1;i<=M;i++)
printf("\t %-11d%-8d%-8d%d\n",tree[i].weight,tree[i].prents,tree[i].lchild,tree[i].rchild);
printf("\n\n------------------------------------------------------------------\n\n\n");
}
void sethufcode() //建立huffman编码
{
int i,s,f,k=1;
struct codetype c;
for(i=1;i<=N;i++)
{
c=user[i].code;
c.start=N+1;
s=i;
f=tree[s].prents;
do
{
c.start--;
if(s==tree[f].lchild)
c.bits[c.start]='0';
else
c.bits[c.start]='1';
s=f;
f=tree[s].prents;
}while(f);
user[i].code=c;
}
}
void printhufcode() //输出huffman编码,即空格+26个大写字母
{
int i,j;
struct codetype c;
printf("编码为:\n");
for(i=1;i<=N;i++)
{
printf("%c:",user[i].symbol);
c=user[i].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf("\n");
}
printf("\n\n--------------------------------------------------------------------\n\n");
}
void setcode() //对字符进行编码
{
int i,j,count;
char c0,k='Y';
struct codetype c;
while(k=='Y') //利用循环,实现对字符多次编码
{
printf("\n\n请输入字符(大写字母+空格,不超过100),输入'.'(+回车)号结束\n\n");
for(i=1;i<=100;i++) //利用循环,实现对字符输入
{
c0=getchar();
t[i].symbol=c0;
if(c0=='.') break;
}
count=i; //记录字符个数
printf("\n\n--------------------------------------------------------------------\n\n");
printf("\n\n字符编码为:\n\n");
for(i=1;i<=count;i++) //利用循环,实现对字符输出
{
if(t[i].symbol=='.')break;
else
switch(t[i].symbol) //利用开关语句,查找编码
{
case ' ':
c=user[1].code;
for(j=c.start;j<=N;j++) //输出编码
printf("%C",c.bits[j]);
printf(" ");
break;
case 'A':
c=user[2].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf(" ");
break;
case 'B':
c=user[3].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf(" ");
break;
case 'C':
c=user[4].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf(" ");
break;
case 'D':
c=user[5].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf(" ");
break;
case 'E':
c=user[6].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf(" ");
break;
case 'F':
c=user[7].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf(" ");
break;
case 'G':
c=user[8].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf(" ");
break;
case 'H':
c=user[9].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf(" ");
break;
case 'I':
c=user[10].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf(" ");
break;
case 'J':
c=user[11].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf(" ");
break;
case 'K':
c=user[12].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf(" ");
break;
case 'L':
c=user[13].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf(" ");
break;
case 'M':
c=user[14].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf(" ");
break;
case 'N':
c=user[15].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf(" ");
break;
case 'O':
c=user[16].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf(" ");
break;
case 'P':
c=user[17].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf(" ");
break;
case 'Q':
c=user[18].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf(" ");
break;
case 'R':
c=user[19].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf(" ");
break;
case 'S':
c=user[20].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf(" ");
break;
case 'T':
c=user[21].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf(" ");
break;
case 'U':
c=user[22].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf(" ");
break;
case 'V':
c=user[23].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf(" ");
break;
case 'W':
c=user[24].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf(" ");
break;
case 'X':
c=user[25].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf(" ");
break;
case 'Y':
c=user[26].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf(" ");
break;
case 'Z':
c=user[27].code;
for(j=c.start;j<=N;j++)
printf("%c",c.bits[j]);
printf(" ");
break;
default:
printf(" *此编码找不到,请检查输入是否正确* ");
}
}
printf("\n\n\n--------------------------------------------------------------------\n\n");
printf("\n\n\n----- 继续??(Y/N) -----\n");
getchar();
printf("\n");
scanf("%c",&k);
getchar();
printf("\n\n*********************************************************\n\n");
}