哈夫曼编解码器C语言可运行

#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;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

灵舒敲代码

我的公v是cxyy1106,欢

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值