哈夫曼树相关操作(C-数据结构)

题目

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

思路

每次寻找最小的且之前没有作为子节点的两个节点作为子节点生成新的双亲结点,依次进行,直到只剩一个节点(该节点相当于根节点)。对于获取哈夫曼编码,就从叶子节点开始,依次遍历其双亲结点,每次判断之前的子节点是左还是右并进行对应标记,记录下来所有叶子节点的编码,即可得所有字符的编码,从而可以求出字符串的编码。具体结合代码理解。

代码

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#define MAXSIZE 10000
#define MAXNUM 999999

typedef struct {
	int weight;
	int parent;
	int LChild;
	int RChild;
}HuffmanTree;

HuffmanTree huffman[MAXSIZE];
char str[MAXSIZE];
int w[MAXSIZE];
char strHuff[200][MAXSIZE];


void Select(HuffmanTree* ht, int n, int* s1, int* s2);		// 搜索节点
void CrtHuffmanTree(HuffmanTree* ht, int w[], int n);		// 创建哈夫曼树
void CrtHuffmanCode(HuffmanTree* ht, int n, char str[]);		// 哈夫曼编码
void printHuffmanTree(HuffmanTree* ht, int n);				// 打印哈夫曼树


int main()
{
	int n;
	printf("请输入字符个数:");
	scanf("%d",&n);
	getchar();
	printf("请输入这些字符:");
	for(int i=0;i<n;i++){
		scanf("%c",&str[i]);
		getchar();
	} 
	printf("请输入这些字符对应的权值:");
	for (int i = 0; i < n; i++){ 
		scanf("%d", &w[i]);
	} 
	CrtHuffmanTree(huffman, w, n);
	CrtHuffmanCode(huffman, n, str);
	char s1[MAXSIZE];
	printf("请输入要编码的字符串:"); 
	scanf("%s",s1);
	 printf("编码结果为:");
	 for(int i=0;i<strlen(s1);i++){
	 	printf("%s",strHuff[(int)s1[i]]);
	 } 
	return 0;
}
void Select(HuffmanTree* ht, int n, int* i1, int* i2) // 搜索两个最小节点
{
	int min1=MAXNUM,min2=MAXNUM;
	*i1=0;
	*i2=0;
	for(int i=1;i<=n;i++){
		if(ht[i].parent==0){
			if(ht[i].weight<min1){
				min2=min1;
				*i2=*i1;
				min1=ht[i].weight;
				*i1=i;
			}else{
				if(ht[i].weight<min2){
					min2=ht[i].weight;
					*i2=i;
				}
			}
		}
	}
}
void CrtHuffmanTree(HuffmanTree* ht, int w[], int n) // 创建哈夫曼树
{
	int i;
	int m = 2 * n - 1;

	for (i = 1; i <= n; i++)
	{		
		//1至n号单元存放叶子结点,初始化
		ht[i].weight = w[i - 1];
		ht[i].parent = 0;
		ht[i].LChild = 0;
		ht[i].RChild = 0;
	}
	for (i = n + 1; i <= m; i++) 
	{	
		// n+1至m号单元存放非叶结点,初始化
		ht[i].weight = 0;
		ht[i].parent = 0;
		ht[i].LChild = 0;
		ht[i].RChild = 0;
	}

	printf("初始的哈夫曼树为\n");
	printHuffmanTree(ht, 2 * n - 1);

	// 初始化完毕,开始创建非叶结点
	int s1, s2;
	for (i = n + 1; i <= m; i++) 
	{	
		// 创建非叶结点,建哈夫曼树
		Select(ht, i - 1, &s1, &s2);
		ht[i].weight = ht[s1].weight + ht[s2].weight;
		ht[s1].parent = i;
		ht[s2].parent = i;
		ht[i].LChild = s1;
		ht[i].RChild = s2;
	}

	printf("构建后的哈夫曼树为\n");
	printHuffmanTree(ht, 2 * n - 1);
}

void CrtHuffmanCode(HuffmanTree* ht, int n, char str[]) // 哈夫曼编码
{
	//从叶子结点到根,逆向求每个叶子结点(共n个)对应的哈夫曼编码
	char* cd= (char*)malloc(n * sizeof(char));
	memset(cd, -1, n);
	for (int i = 1; i <= n; i++) 
	{			
		//求n个叶子结点对应的哈夫曼编码
		int start = n, c = i, p = ht[i].parent;
		while (p != 0) {
			--start;
			if (ht[p].LChild == c)			//左分支标0
				cd[start] = '0';
			else
				cd[start] = '1';			//右分支标1
			c = p;							//向上倒推 
			p = ht[p].parent;
		}
		printf("%c的编码:", str[i - 1]);
		int cnt=0;
		for (int j = 0; j < n; j++) 
		{
			if (cd[j] == '0' || cd[j] == '1'){
				printf("%c", cd[j]);
				strHuff[(int)str[i-1]][cnt++]=cd[j];
			}
		}
		printf("\n");
		memset(cd, -1, n);
	}
}
void printHuffmanTree(HuffmanTree* ht, int n)  //打印哈夫曼树 
{
	printf("结点  weigh  parent LChild RChild\n");
	for (int i = 1; i <= n; i++)
		printf("%d\t%d\t%d\t%d\t%d\n", i, ht[i].weight, ht[i].parent, ht[i].LChild, ht[i].RChild);
	printf("\n");
}

运行结果

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

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

漠–

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值