/**************************************************************************************
47. 某些密码由 N 个英文字母组成(N〈26), 每个字母的平均使用率为:W1,W2,...
,Wn, 要求编程完成下列任务:
① 键入英文字母及个数;
② 键入N个英文字母的使用频率;
③ 用二进制数对该N个英文字母进行编码(最短,无二义性);
④ 键入字母短文(单词用空格区分),输出相应编码;
⑤ 键入二进制编码短文,输出译文。
***********************************************************************************/
#include <stdio.h>
#include <malloc.h>
#include <cstdlib>
typedef struct
{
int weight;
int parent;
int lchild;
int rchild;
} HuffNode;
int N; //英文字母的个数
char *letters; //保存英文字母数组的指针
HuffNode *huffnodes;
void CreateHuffTree()
{
int i,j;
int min1, min2;
FILE *fp;
fp = fopen("letters.txt","r");
if(fp==NULL)
exit(-1);
printf("请输入英文字母的个数N(N<=26):");
fscanf(fp,";%d",&N);
printf("%d\n",N);
letters = (char*)malloc(N*sizeof(char));
huffnodes = (HuffNode*)malloc((2*N-1)*sizeof(HuffNode));
printf("请输入%d个英文字母:\n",N);
for(i=0; i<N; i++)
{
fscanf(fp, ";%c", &letters[i]);
printf("%c ",letters[i]);
}
printf("\n请输入上述字母对应的平均使用频率:\n");
for(i=0; i<N; i++)
{
fscanf(fp, ";%d", &huffnodes[i].weight);
huffnodes[i].parent = -1;
huffnodes[i].lchild = -1;
huffnodes[i].rchild = -1;
printf("%d ",huffnodes[i].weight);
}
printf("\n");
fclose(fp);
for(i=N; i<2*N-1; i++)
{
j=i-1;
//找到第一个树根
while(huffnodes[j].parent != -1) j--;
min1 = j--;
//找到第二个树根
while(huffnodes[j].parent != -1) j--;
min2 = j--;
//交换,使min1最小,min2次小
if(huffnodes[min1].weight > huffnodes[min2].weight)
{
int tmp;
tmp = min1;
min1 = min2;
min2 = tmp;
}
for(; j>=0; j--)
{
if(huffnodes[j].parent == -1)
{
if(huffnodes[j].weight < huffnodes[min1].weight)
{
min2 = min1;
min1 = j;
}
else if(huffnodes[j].weight < huffnodes[min2].weight)
min2 = j;
}
}
huffnodes[i].weight = huffnodes[min1].weight + huffnodes[min2].weight;
huffnodes[i].lchild = min1;
huffnodes[i].rchild = min2;
huffnodes[i].parent = -1;
huffnodes[min1].parent = i;
huffnodes[min2].parent = i;
}
}
void DestroyHuffTree()
{
if(letters)
free(letters);
if(huffnodes)
free(huffnodes);
}
void EncodeLetters()
{
int i,j,k,t;
char *code;
char tmp;
printf("\n----字母编码----\n");
code = (char*)malloc(N*sizeof(char));
for(t=0; t<N; t++)
{
j = i = t; k = 0;
while(huffnodes[j].parent != -1)
{
j = huffnodes[j].parent;
if(huffnodes[j].lchild == i)
code[k++] = '0';
else code[k++] = '1';
i = j;
}
code[k] = '\0';//结束符
for(i=0; i<k/2; i++)//头尾置换
{
tmp = code[i];
code[i] = code[k-i-1];
code[k-i-1] = tmp;
}
printf("%c : %s\n",letters[t],code);
}
free(code);
}
void Encode(char* lets)
{
int i,j,k,t;
char *code;
char tmp;
FILE* fp;
fp = fopen("encode.txt","w");
code = (char*)malloc(N*sizeof(char));
for(t = 0; lets[t] != '\0'; t++)
{
for(i=0; i<N; i++)
{
if(letters[i] == lets[t])
break;
}
j = i; k = 0;
while(huffnodes[j].parent != -1)
{
j = huffnodes[j].parent;
if(huffnodes[j].lchild == i)
code[k++] = '0';
else code[k++] = '1';
i = j;
}
code[k] = '\0';//结束符
for(i=0; i<k/2; i++)//头尾置换
{
tmp = code[i];
code[i] = code[k-i-1];
code[k-i-1] = tmp;
}
fprintf(fp,code);
}
free(code);
fclose(fp);
}
void Decode()
{
char ch;
FILE *ifp,*ofp;
int i,j,flag;
ifp = fopen("encode.txt","r");
if(!ifp)
{
printf("fail to read the encode.txt!\n");
return;
}
ofp = fopen("decode.txt","w");
do
{
i = 2*N-1-1;
while(huffnodes[i].lchild != -1 && huffnodes[i].rchild != -1)
{
flag = fscanf(ifp,"%c",&ch);
if(flag == EOF)
break;
if(ch == '0')
j = huffnodes[i].lchild;
else j = huffnodes[i].rchild;
i = j;
}
//写入Decode
fprintf(ofp,"%c",letters[i]);
}while(flag != EOF);
fclose(ifp);
fclose(ofp);
}
void Encode_1(char *lets)
{
int i,j,k,t;
char *code;
char tmp;
code = (char*)malloc(N*sizeof(char));
for(t = 0; lets[t] != '\0'; t++)
{
for(i=0; i<N; i++)
{
if(letters[i] == lets[t])
break;
}
j = i; k = 0;
while(huffnodes[j].parent != -1)
{
j = huffnodes[j].parent;
if(huffnodes[j].lchild == i)
code[k++] = '0';
else code[k++] = '1';
i = j;
}
code[k] = '\0';//结束符
for(i=0; i<k/2; i++)//头尾置换
{
tmp = code[i];
code[i] = code[k-i-1];
code[k-i-1] = tmp;
}
printf(code);
}
free(code);
printf("\n");
}
void Decode_1(char *codes)
{
int i,j,k=0;
int ch;
do
{
i = 2*N-1-1;
while(huffnodes[i].lchild != -1 && huffnodes[i].rchild != -1)
{
ch = codes[k++];
if(ch == '\0')
break;
if(ch == '0')
j = huffnodes[i].lchild;
else j = huffnodes[i].rchild;
i = j;
}
//写入Decode
printf("%c",letters[i]);
}while(ch != '\0');
printf("\n");
}
void PrintNodes()
{
int i;
printf("\n----huffmantree----\n");
for(i=0; i<2*N-1; i++)
{
printf("%4d",huffnodes[i].weight);
printf("%4d",huffnodes[i].parent);
printf("%4d",huffnodes[i].lchild);
printf("%4d\n\n",huffnodes[i].rchild);
}
}
void main()
{
int isel;
char lets[100];
char codes[100];
CreateHuffTree();
// PrintNodes();
EncodeLetters();
printf("\n请选择一个操作: 1-编码, 2-译码\n");
scanf("%d",&isel);
switch(isel)
{
case 1:
printf("请输入字母短文:\n");
scanf("%s",lets);
printf("编码为:\n");
Encode_1(lets);
break;
case 2:
printf("请输入二进制编码短文:\n");
scanf("%s",codes);
printf("译码为:\n");
Decode_1(codes);
break;
}
DestroyHuffTree();
}
练习47
最新推荐文章于 2021-11-12 19:53:20 发布