数据结构 C语言 哈夫曼编码 哈夫曼树 文件操作

【问题描述】

利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码(复原)。对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编/译码系统。试为这样的信息收发站写一个哈夫曼码的编/译码系统。

【任务要求】

一个完整的系统应具有以下功能:

1)      I:初始化(Initialization)。从终端读入字符集大小n,以及n个字符和n个权值,建立哈夫曼树,并将它存于文件hfmTree中。

2)      E:编码(Encoding)。利用已建好的哈夫曼树(如不在内存,则从文件hfmTree中读入),对文件ToBeTran中的正文进行编码,然后将结果存入文件CodeFile中。

3)      D:译码(Decoding)。利用已建好的哈夫曼树将文件CodeFile中的代码进行译码,结果存入文件TextFile中。

【测试数据】

用下表给出的字符集和频度的实际统计数据建立哈夫曼树,并实现以下报文的编码和译码:“THIS PROGRAM IS MY FAVORITE”。

#include<stdio.h>
#include<stdlib.h>
#define N 27
typedef struct {
	char ch;
	int weight;
	int lchild, rchild, parents;
}huffmanTree;

typedef struct {
	char bits[N];
	int start;
	char ch;
}huffmanCode;

int createHuffman(huffmanTree tree[], int n)
{
	int i, j;
	int min, cmin;
	int m, cm;
	char ch;

	printf("请输入所有字符(每个字符后面一个回车):\n");
	for (i = 0; i < n; i++) {
		ch = getchar();
		tree[i].ch = ch;
		getchar();
	}
	printf("ok\n请输入所有权值:\n");
	for (i = 0; i < n; i++) {
		tree[i].lchild = tree[i].rchild = tree[i].parents = -1;
		scanf("%d", &tree[i].weight);
	}
	for (i = n; i < 2 * n - 1; i++) {
		min = cmin = 9999999;
		m = cm = 0;
		for (j = 0; j < i; j++) {
			if (tree[j].parents == -1) {
				if (tree[j].weight < cmin) {
					min = cmin;
					m = cm;
					cmin = tree[j].weight;
					cm = j;
				}
				else if (tree[j].weight < min) {
					min = tree[j].weight;
					m = j;
				}
			}

		}
		tree[i].weight = tree[m].weight + tree[cm].weight;
		tree[i].lchild = m;
		tree[i].rchild = cm;
		tree[i].parents = -1;
		tree[m].parents = i;
		tree[cm].parents = i;
	}
	return 0;
}

int incode(huffmanTree *tree, huffmanCode *code)
{
	int i, parent, child;
	huffmanCode temp;
	for (i = 0; i < N; i++) {
		child = i;
		parent = tree[child].parents;
		temp.start = N;
		while (parent != -1) {
			if (tree[parent].lchild == child) {
				temp.bits[--temp.start] = '0';
			}
			else {
				temp.bits[--temp.start] = '1';
			}
			child = parent;
			parent = tree[child].parents;
		}
		code[i] = temp;
	}
}

int huffcode(huffmanTree *tree, huffmanCode *code)
{
	char c;
	int j, index;
	FILE *fp, *write;
	if ((fp = fopen("ToBeTran.txt", "r")) == NULL) {
		printf("文件读取失败\n");
		return 0;
	}
	if ((write = fopen("CodeFile.txt", "w")) == NULL) {
		printf("文件读取失败\n");
		return 0;
	}

	c = fgetc(fp);
	while (c != '#') {
		if (c == 32) {
			for (j = code[0].start; j <= N - 1; j++) {
				fprintf(write, "%c", code[0].bits[j]);
			}
		}
		else {
			index = c - 'A' + 1;
			for (j = code[index].start; j <= N - 1; j++) {
				fprintf(write, "%c", code[index].bits[j]);
			}
		}
		c = fgetc(fp);
	}
	fprintf(write,"#");
	fclose(fp);
	fclose(write);
	return 0;
}

int decode(huffmanTree *tree, huffmanCode *code)
{
	int i;
	char b;
	FILE *fp, *write;
	if ((fp = fopen("CodeFile.txt", "r")) == NULL) {
		printf("文件读取失败\n");
		return 0;
	}
	if ((write = fopen("TextFile.txt", "w")) == NULL) {
		printf("文件读取失败\n");
		return 0;
	}

	b = fgetc(fp);
	i = 2 * N - 2;
	while (b != '#')
	{
		if (b == '0')
			i = tree[i].lchild;
		else if (b == '1')
			i = tree[i].rchild;
		if (tree[i].lchild == -1)
		{
			fprintf(write, "%c", tree[i].ch);
			i = 2 * N - 2;
		}
		b = fgetc(fp);
	}
	if (tree[i].lchild != -1 && i != 2 * N - 2) {
		printf("电文有错\n");
	}
	fclose(fp);
	fclose(write);
}


int main()
{
	FILE *fp, *du;
	int i, n, j;
	huffmanTree *tree;
	huffmanCode *code;

	printf("请输入个数:\n");
	scanf("%d", &n);
	getchar();
	tree = (huffmanTree*)malloc(sizeof(huffmanTree)*(2 * n - 1));
	code = (huffmanCode*)malloc(sizeof(huffmanCode) * n);
	if ((fp = fopen("hfmTree.txt", "w")) == NULL) {
		printf("文件打开失败\n");
	}

	createHuffman(tree, 27);
	//------------------------------------------------------------------------------------------------------------------------
	//写文件
	for (i = 0; i < n; i++) {
		fprintf(fp,"%c %d %d %d %d\n", tree[i].ch, tree[i].parents, tree[i].lchild, tree[i].rchild, tree[i].weight);
	}
	for (i = n; i < 2 * n - 1; i++) {
		fprintf(fp, "%d %d %d %d\n", tree[i].parents, tree[i].lchild, tree[i].rchild, tree[i].weight);
	}
	fclose(fp);
	/*for (i = 0; i < 2 * n - 1; i++) {
		printf("%c,%d,%d,%d,%d\n", tree[i].ch, tree[i].parents, tree[i].lchild, tree[i].rchild, tree[i].weight);
	}*/
	//------------------------------------------------------------------------------------------------------------------------
	//读树文件
	if ((du = fopen("hfmTree.txt", "r")) == NULL) {
		printf("打开文件失败\n");
	}
	for (i = 0; i < n; i++) {
		fscanf(du, "%d %d %d %d\n", &tree[i].parents, &tree[i].lchild, &tree[i].rchild, &tree[i].weight);
	}
	for (i = n; i < 2 * n - 1; i++) {
		fscanf(du, "%d %d %d %d\n", &tree[i].parents, &tree[i].lchild, &tree[i].rchild, &tree[i].weight);
	}
	fclose(du);
	//------------------------------------------------------------------------------------------------------------------------
	/*for (i = 0; i < 2 * n - 1; i++) {
		printf("%c,%d,%d,%d,%d\n", tree[i].ch, tree[i].parents, tree[i].lchild, tree[i].rchild, tree[i].weight);
	}*/

	incode(tree, code);
	for (i = 0; i < N; i++) {
		printf("%c : ", tree[i].ch);
		for (j = code[i].start; j <= N - 1; j++) {
			printf("%c", code[i].bits[j]);
		}
		printf("\n");
	}
	huffcode(tree, code);
	decode(tree, code);
	fclose(fp);
	system("pause");
	return 0;
}

  • 10
    点赞
  • 140
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
好的,您想了解关于C语言哈夫曼编码译码器课设和数据结构课程设计哈夫曼编码译码器的相关知识,我可以为您提供一些基本的信息。 哈夫曼编码是一种基于统计概率的编码方法,可以将每个字符使用不同长度的二进制编码表示,使得出现频率较高的字符使用较短的编码,出现频率较低的字符使用较长的编码,从而达到压缩数据的效果。 哈夫曼编码译码器的实现需要用到数据结构中的哈夫曼树哈夫曼编码表。哈夫曼树是一种特殊的二叉树,它的叶子节点对应着每个字符,而每个字符的编码可以通过从根节点到该字符的路径上的边的方向来表示。哈夫曼编码表则是一个字符与其对应的二进制编码之间的映射表。 在C语言中,可以使用结构体来表示哈夫曼树哈夫曼编码表。哈夫曼树的节点可以定义为一个结构体,包含字符、权值和左右子节点指针等属性。而哈夫曼编码表则可以定义为一个数组,每个元素表示一个字符与其对应的编码。 哈夫曼编码译码器的实现过程可以分为两个步骤:编码和译码。编码过程中,需要先统计原始数据中各个字符出现的频率,然后根据频率构建哈夫曼树,生成哈夫曼编码表,并将原始数据按照哈夫曼编码进行压缩。译码过程中,则需要通过哈夫曼编码表将压缩后的二进制数据还原成原始数据。 以上是关于C语言哈夫曼编码译码器课设和数据结构课程设计哈夫曼编码译码器的基本介绍,希望对您有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值