#define MAX_String_Code 10000
#define MAX_String_Length 1500
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
typedef struct
{
float weight;
int lchild, rchild, parent;
} HTNode, * HuffmanTree;
typedef struct
{
char code[1000];
int start;
}HuffmanCode;
typedef struct
{
char c;
float count;
float w;
}charlist;
void menu()
{
printf("\t\t\t\t\t****************************\n");
printf("\t\t\t\t\t* 哈夫曼编解码器 *\n");
printf("\t\t\t\t\t****************************\n");
printf("\t\t\t\t\t* 1.统计文本信息 *\n");
printf("\t\t\t\t\t* 2.哈夫曼编码 *\n");
printf("\t\t\t\t\t* 3.编码 *\n");
printf("\t\t\t\t\t* 4.解码 *\n");
printf("\t\t\t\t\t* 5.检验解码正确性 *\n");
printf("\t\t\t\t\t* 6.重置data文本 *\n");
printf("\t\t\t\t\t* 7.退出 *\n");
printf("\t\t\t\t\t****************************\n");
printf("请依次顺序操作. . .\n");
}
void Init(char str[], charlist list[], int* length, int* n)
{
int i, j, k;
float a;
char b[2] = { '0','\0' };
FILE* fp1;
fp1 = fopen("encode.txt", "w");
fputs(b, fp1);
fclose(fp1);
fp1 = fopen("decode.txt", "w");
fputs(b, fp1);
fclose(fp1);
fp1 = fopen("data.txt", "r");
if (fp1 == NULL)
{
printf("data.txt文件不存在,请输入需要编码的内容:");
fp1 = fopen("data.txt", "w");
gets(str);
fputs(str, fp1);
fclose(fp1);
printf("需编码的内容已存进data.txt中. . .\n");
system("pause");
system("cls");
}
else
{
fgets(str, MAX_String_Length, fp1);
fclose(fp1);
}
*length = strlen(str);
a = (float)*length;
for (i = 1, k = 0; k < *length; i++, k++)
{
for (j = 1; j <= i; j++)
{
if (str[k] == list[j].c)
{
(list[j].count)++;
i--;
break;
}
}
if (str[k] == list[j].c)
continue;
else
{
list[i].c = str[k];
list[i].count = 1;
}
}
*n = i - 1;
for (i = 1; i <= *n; i++)
list[i].w = list[i].count / a;
}
void Select(HuffmanTree HT, int n, int* s)
{
float min;
int i, j;
for (j = 1; j <= n; j++) {
if (HT[j].parent == 0) {
*s = j;
min = HT[j].weight;
break;
}
}
for (i = j + 1; i <= n; i++) {
if (HT[i].weight < min && HT[i].parent == 0) {
*s = i;
min = HT[i].weight;
}
}
HT[*s].parent = 1;
}
void CountList(charlist list[], int n)
{
int i;
for (i = 1; i <= n; i++)
printf("字符%c出现了%3d次,出现的概率为%f\n", list[i].c, (int)list[i].count, list[i].w);
}
int Huffmancoding(HuffmanTree HT, HuffmanCode* HC, int n, charlist list[])
{
HuffmanCode cd;
int s1, s2;
int i, j, m, c, f;
if (n <= 1) return 0;
m = 2 * n - 1;
for (i = 1; i <= n; ++i)
{
HT[i].weight = list[i].w;
HT[i].parent = 0;
HT[i].lchild = 0;
HT[i].rchild = 0;
}
for (; i <= m; ++i)
{
HT[i].weight = 0;
HT[i].parent = 0;
HT[i].lchild = 0;
HT[i].rchild = 0;
}
for (i = n + 1; i <= m; ++i)
{
Select(HT, i - 1, &s1);
Select(HT, i - 1, &s2);
HT[s1].parent = i;
HT[s2].parent = i;
HT[i].lchild = s1;
HT[i].rchild = s2;
HT[i].weight = HT[s1].weight + HT[s2].weight;
}
for (i = 1; i <= n; ++i)
{
cd.start = n - 1;
for (c = i, f = HT[i].parent; f != 0; c = f, f = HT[f].parent)
{
if (HT[f].lchild == c)
cd.code[--cd.start] = '0';
else
cd.code[--cd.start] = '1';
}
for (j = cd.start; j < n - 1; j++)
{
HC[i].code[j] = cd.code[j];
}
HC[i].code[j] = '\0';
HC[i].start = cd.start;
}
for (i = 1; i <= n; i++)
{
printf("%c的哈夫曼编码是:", list[i].c);
for (j = HC[i].start; HC[i].code[j] != '\0'; j++)
{
printf("%c", HC[i].code[j]);
}
printf("\n");
}
HC[0].code[0] = '1';
return 1;
}
void EnCode(char str[], HuffmanCode* HC, charlist list[], int n, int m)
{
int i, j, k, h = 0;
char num[MAX_String_Code];
FILE* fp2;
HuffmanCode* hc;
hc = (HuffmanCode*)malloc(MAX_String_Length * sizeof(HuffmanCode));
if (HC[0].code[0] == '0')
{
printf("操作失败,请先进行哈夫曼编码操作. . .\n");
return;
}
for (i = 0; i < m; i++)
{
for (k = 1; k <= n; k++)
if (str[i] == list[k].c)
break;
hc[i] = HC[k];
}
for (i = 0; i < m; i++)
{
for (j = hc[i].start; hc[i].code[j] != '\0'; j++)
{
num[h] = hc[i].code[j];
h++;
}
}
num[h] = '\0';
fp2 = fopen("encode.txt", "w");
printf("编码成功,已保存到encode文本中,编码码内容为:\n");
fputs(num, fp2);
fclose(fp2);
puts(num);
}
void DeCode(charlist list[], HuffmanTree HT, int n)
{
FILE* fp3;
int p, h;
char num[MAX_String_Code];
int i = 0;
fp3 = fopen("encode.txt", "r");
fgets(num, MAX_String_Code, fp3);
if (strlen(num) == 1)
{
printf("操作失败,请先完成前几步操作后再执行此操作. . .\n");
return;
}
fclose(fp3);
p = 2 * n - 1;
h = strlen(num);
fp3 = fopen("decode.txt", "w");
printf("解码成功,已保存到decode文本中,解码内容为:\n");
while (i < h)
{
while (HT[p].lchild != 0 && HT[p].rchild != 0)
{
if (num[i] == '0')
p = HT[p].lchild;
else
p = HT[p].rchild;
i++;
}
printf("%c", list[p].c);
fprintf(fp3, "%c", list[p].c);
p = 2 * n - 1;
}
fclose(fp3);
printf("\n");
}
void Check()
{
int k;
FILE* fp4;
char str1[MAX_String_Length];
char str2[MAX_String_Length];
fp4 = fopen("data.txt", "r");
fgets(str1, MAX_String_Length, fp4);
fclose(fp4);
fp4 = fopen("decode.txt", "r");
fgets(str2, MAX_String_Length, fp4);
if (strlen(str2) == 1)
{
printf("请先进行解码操作后再执行此操作. . .\n");
return;
}
printf("data.txt中的内容为:\n");
puts(str1);
printf("decode.txt中的内容为:\n");
puts(str2);
fclose(fp4);
k = strcmp(str1, str2);
if (k == 0)
printf("经检验解码正确!\n");
else
printf("经检验解码错误!\n");
}
int main()
{
FILE* fp;
HuffmanCode* HC;
HuffmanTree HT;
charlist* list;
int n = 0, length = 0;
int t;
char* str;
int flag;
str = (char*)malloc(1500 * sizeof(char));
list = (charlist*)malloc(128 * sizeof(charlist));
printf("欢迎使用哈夫曼编解码器\n");
system("pause");
system("cls");
Init(str, list, &length, &n);//初始化&&统计
HT = (HuffmanTree)malloc((2 * n + 2) * sizeof(HTNode));
HC = (HuffmanCode*)malloc(128 * sizeof(HuffmanCode));
HC[0].code[0] = '0';
do
{
menu();
printf("请输入你的选择(1-7):");
scanf("%d", &t);
switch (t)
{
case 1:
CountList(list, n);
system("pause");
system("cls");
break;
case 2:
flag = Huffmancoding(HT, HC, n, list);//哈夫曼编码
if (flag == 1)
{
printf("编码成功\n");
}
else
{
printf("只能对两种字符以上经行编码\n");
}
system("pause");
system("cls");
break;
case 3:
EnCode(str, HC, list, n, length);//编码
system("pause");
system("cls");
break;
case 4:
DeCode(list, HT, n);//译码
system("pause");
system("cls");
break;
case 5:
Check();
system("pause");
system("cls");
break;
case 6:
if (str != NULL) {
free(str);
str = NULL;
}
str = (char*)malloc(1500 * sizeof(char));
printf("请输入重新要存入文本的内容:\n");
getchar();
fp = fopen("data.txt", "w");
gets(str);
fputs(str, fp);
fclose(fp);
if (list != NULL) {
free(list);
list = NULL;
}
if (HC != NULL) {
free(HC);
HC = NULL;
}
if (HT != NULL) {
free(HT);
HT = NULL;
}
list = (charlist*)malloc(128 * sizeof(charlist));
printf("重置成功,需编码的内容已存进data.txt中. . .\n");
Init(str, list, &length, &n);//初始化&&统计
HT = (HuffmanTree)malloc((2 * n + 2) * sizeof(HTNode));
HC = (HuffmanCode*)malloc(128 * sizeof(HuffmanCode));
HC[0].code[0] = '0';
system("pause");
system("cls");
break;
case 7:
printf("退出成功!!!");
break;
default:
if ('A' < t <= 'Z' || 'a' < t <= 'z')
getchar();
printf("输入有误!!!");
system("pause");
system("cls");
break;
}
} while (t != 7);
return 0;
}
哈夫曼编解码器C语言可运行
最新推荐文章于 2024-01-04 16:46:01 发布