实验四 基于哈夫曼树的数据压缩算法

实验四 基于哈夫曼树的数据压缩算法
一、实验目的
1.掌握哈夫曼树的构造算法。
2.掌握哈夫曼编码的构造算法。

二、实验内容
问题描述
输入一串字符串,根据给定的字符串中字符出现的频率建立相应的哈夫曼树,
构造哈夫曼编码表,在此基础上可以对压缩文件进行压缩(即编码),同时可以对
压缩后的二进制编码文件进行解压(即译码)

三、实验实习设备及开发环境
Visual studio 2022
四.实验实习过程步骤(注意是主要关键步骤,不是所有步骤,适当文字+截图说明)
Function1:对输入的字符串进行计数,计算权重
在这里插入图片描述

Function2:根据权重创建哈夫曼树,选择权重和最小的两个,然后结合成一个新的节点,并且把原来的两个子节点删除(标记双亲结点)

在这里插入图片描述
在这里插入图片描述

Function3:进行哈夫曼编码,从根节点开始,一步一步找到双亲结点,如果是双亲结点的左子树,就记0,如果是双亲结点的右子树就是1,因为是从最底下的叶子节点开始的,所以得到的编码是反的,需要变成正的。
在这里插入图片描述

Function4:译码,从得到的编码开始,从根结点出发,如果是0就往左子树找到子节点,如果是1就往右找到子节点,一直回溯,直到找到了叶子节点。然后再从根节点出发,找下一个原来的文本。
在这里插入图片描述

五、实验实习结果及分析
在这里插入图片描述

实验结果按照要求输出。
六.实验遇到的问题及解决办法,实验心得体会及对此实验的意见或建议(有就写,无可不写)。
对于字符串的比较要用字符串操作的函数,不能直接进行操作,一定要记住。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 100

typedef struct
{
	int weight;
	int parent, lchild, rchild;
}HTNode,*HuffmanTree;

int* getcount(char *str,int *n)
{
	int* counter = calloc(26,sizeof(counter));
	int length = strlen(str);
	*n = 0;
	int i;
	int j = 0;
	for (i = 0; i < length; i++)
	{
		counter[str[i] - 'a']++;
	}
	for (i= 0; i < 26; i++)
	{
		if (counter[i] != 0)
		{
			j++;
		}
	}
	*n = j;
	for (i = 0; i <26; i++)
	{
		if (counter[i] != 0)
		{
			printf("%c:%d ", i + 'a', counter[i]);
		}
	}
	printf("\n");
	return counter;

}

void select(HuffmanTree HT, int* small, int* small2,int num)
{
	int mini=100000;
	int i;
	for (i = 1; i <= num; i++)
	{
		if (HT[i].parent == 0)
		{
			if (HT[i].weight < mini)
			{
				mini = HT[i].weight;
				*small = i;
			}
		}
		
	}
	mini = 10000;
	for (i = 1; i <= num; i++)
	{
		if (HT[i].parent == 0 && HT[i].weight < mini && i != *small)
		{
			mini = HT[i].weight;
			*small2 = i;
		}
	}


}
void createHuffmantree(HTNode* HT, int n,int *counter)
{
	//初始化
	if (n <= 1)
		return;
	int m = 2 * n - 1;
	int i;
	for (i = 1; i <= m ; i++)
	{
		HT[i].lchild = 0;
		HT[i].rchild = 0;
		HT[i].parent = 0;
	}
	for (i = 1; i <= n; i++)
	{
		HT[i].weight = counter[i - 1];
	}
	//创建树
	int small=0, small2=0;
	for (i = n + 1; i <= m; i++)
	{
		select(HT, &small, &small2, i-1);
		HT[i].weight = HT[small].weight + HT[small2].weight;
		HT[i].lchild = small;
		HT[i].rchild = small2;
		HT[small].parent = i;
		HT[small2].parent = i;
	}

}
void printHuffmaxtree(HTNode* HT, int n)
{
	int i;
	for (i = 1; i <= 2*n-1; i++)
	{
		printf("%d %d %d %d %d\n", i, HT[i].weight, HT[i].parent, HT[i].lchild, HT[i].rchild);
	}
}

void Huffmancode(HTNode* HT, char HC[MAX][MAX], int n)
{
	char temp[20];
	int i;
	for (i = 1; i <= n; i++)
	{
		int strm = 0;
		int p = HT[i].parent;
		int c = i;
		int strnumber = 0;
		while (p != 0)
		{
			if (HT[p].lchild == c)
			{
				temp[strnumber] = '0';
			}
			else
			{
				temp[strnumber] = '1';
			}
			strnumber++;
			c = p;
			p = HT[p].parent;
		}
		temp[strnumber] = '\0';
		for (strnumber = strnumber - 1; strnumber >= 0; strnumber--,strm++)
		{
			HC[i][strm] = temp[strnumber];
		}
		HC[i][strm] = '\0';
	}
}

void printsolocode(int* counter, char HC[MAX][MAX],int n,char *str,char *s)
{
	int i;
	for (i = 0; i < 26; i++)
	{
		if (counter[i] != 0)
		{
			printf("%c:%s ", i + 'a', HC[i + 1]);
		}
	}
	printf("\n");
	int j;
	int q = 0;
	for (i = 0; i < strlen(str); i++)
	{
		printf("%s", HC[str[i] - 'a' + 1]);
		for (j = 0; j < strlen(HC[str[i] - 'a' + 1]); j++)
		{
			s[q++] = HC[str[i] - 'a' + 1][j];
		}
	}
	s[q] = '\0';
	printf("\n");
}

void decodeHuffmancode(HTNode* HT, int* counter, int n, char* s)
{
	int length = strlen(s);
	int i = 0;
	int f = 2 * n - 1;
	while (s[i] != '\0')
	{
		if (s[i] == '0')
		{
			f = HT[f].lchild;
		}
		else
		{
			f = HT[f].rchild;
		}
		if (f <= n)
		{
			int count = 0;
			int q = 0;
			while (count < f)
			{
				if (counter[q] != 0)
				{
					count++;
				}
				q++;
			}
			printf("%c", q + 'a' - 1);
			f = 2 * n - 1;
		}
		i++;
	}
	printf("\n");
}
int main()
{
	char inputstr[MAX];
	printf("请输入样例\n");
	int n;
	HTNode* HT=NULL;
	char HC[MAX][MAX];
	char s[MAX];
	char* wholeHC = calloc(20, sizeof(char));
	while (gets(inputstr)&&strcmp(inputstr,"0")!=0)
	{
		int* counter = getcount(inputstr, &n);
		HT = calloc(2 * n, sizeof(HTNode));
		createHuffmantree(HT, n, counter);
		printHuffmaxtree(HT, n);
		Huffmancode(HT, HC, n);
		printsolocode(counter, HC, n,inputstr,s);
		decodeHuffmancode(HT, counter, n, s);
		fflush(stdin);
	}
	return 0;
}
  • 24
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值