【数据结构】哈夫曼树和哈夫曼编码 完整代码

文章详细介绍了如何使用函数模块实现哈夫曼树的构建,包括选择最小和次小权值节点、初始化二叉树、创建哈夫曼树以及求哈夫曼编码的过程。
摘要由CSDN通过智能技术生成

函数模块

哈夫曼树的定义

typedef struct {
	int weight, parent, lc, rc;//权值,双亲,左孩子,右孩子
}HTNode,*HuffmanTree;
typedef char** HuffmanCode;//为存储哈夫曼编码的数组做准备.后期传入参数为指针,不妨直接定义在这里

选择最小、次小权值

void Select(HuffmanTree HT, int n,int &s1, int &s2)//选择最小和次小权值编号的函数
{
	//擂台法选择两值
	s1 = 0; s2 = 0;//最小、次小权值对应编号为s1,s2
	int m1 = 100; int m2 = 100; int i;//最小、次小权值为m1,m2
	for (i = 1; i <= n; i++)
	{
		if (HT[i].parent == 0)
		{
			if (HT[i].weight < m1)
			{
				m2 = m1;
				s2 = s1;
				m1 = HT[i].weight;//更新m1的值
				s1 = i;
			}
			else if (HT[i].weight < m2)
			{
				m2 = HT[i].weight;//更新m2的值
				s2 = i;
			}
		}
	}
}

初始化二叉树、创建并打印哈夫曼树、求哈夫曼编码并打印

void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,int *w, int n)
{
	//初始化二叉树
	if (n <= 1) return; int m = 2 * n - 1;//n个叶子结点的二叉树有2n-1个结点
	int i; HuffmanTree p = HT;
	HT = (HuffmanTree)malloc((m+1)*sizeof(HTNode));//为哈夫曼树分配存储空间;m+1而非m是因为0号位闲置
	for (p = HT + 1, i = 1; i <= n; ++i, ++p, ++w)
	{
		p->weight = *w;
		p->parent = 0;
		p->lc= 0;
		p->rc = 0;
	}
	for (; i <= m; ++i, ++p)
	{
		p->weight = 0;
		p->parent = 0;
		p->lc= 0;
		p->rc= 0;
	}
    /*等价于for (i = 1; i <= n; ++i)
	{
		HT[i].weight = w[i - 1];
		HT[i].lc = 0;
		HT[i].rc = 0;
		HT[i].parent = 0;
	}
	for (; i <= m; ++i, ++p)
	{
		HT[i].weight =0;
		HT[i].lc = 0;
		HT[i].rc = 0;
		HT[i].parent = 0;
	}*/
	//创建哈夫曼树
	int s1,s2;
	for (i = n + 1; i <= m; i++)
	{
		Select(HT,i-1,s1,s2);
		HT[s1].parent = i;
		HT[s2].parent = i;
		HT[i].lc = s1;
		HT[i].rc = s2;
		HT[i].weight = HT[s1].weight + HT[s2].weight;
	}
	printf("创建哈夫曼树如下\n");
	printf("NUM       weight    parent    lc    rc    \n");
	for (i = 1; i <= m; i++)
	{
		printf("HT[%2d] %6d %6d %6d %6d\n", i, HT[i].weight, HT[i].parent, HT[i].lc, HT[i].rc);
	}
	printf("\n");
	//求哈夫曼编码
	int c,start,f; char* cd;
	HC = (HuffmanCode)malloc((n + 1) * sizeof(char*));
	cd = (char*)malloc(n * sizeof(char)); //cd为临时字符数组
	cd[n - 1] = '\0';
	for (i = 1; i <= n; ++i)
	{
		start = n - 1;
		for (c = i, f = HT[i].parent; f != 0; c = f, f = HT[f].parent)
	{
	if (HT[f].lc == c)
	{
		start--;
		cd[start] = '0';
	}
	else
	{
		start--;
		cd[start] = '1';
	}
}
		HC[i] = (char*)malloc((n - start) * sizeof(char));
		strcpy_s(HC[i],n-start+1, &cd[start]);
	}
	free(cd);
	printf("哈夫曼编码如下\n");
	for (i = 1; i <= N; i++)
	{
		printf("HT[%d]编码为\n",i);
		puts(HC[i]);
	}
} 

上级实现

完整代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 8
typedef struct {
	int weight, parent, lc, rc;//权值,双亲,左孩子,右孩子
}HTNode,*HuffmanTree;
typedef char** HuffmanCode;//为存储哈夫曼编码的数组做准备.后期传入参数为指针,不妨直接定义在这里
void Select(HuffmanTree HT, int n,int &s1, int &s2)//选择最小和次小权值编号的函数
{
	//擂台法选择两值
	s1 = 0; s2 = 0;//最小、次小权值对应编号为s1,s2
	int m1 = 100; int m2 = 100; int i;//最小、次小权值为m1,m2
	for (i = 1; i <= n; i++)
	{
		if (HT[i].parent == 0)
		{
			if (HT[i].weight < m1)
			{
				m2 = m1;
				s2 = s1;
				m1 = HT[i].weight;//更新m1的值
				s1 = i;
			}
			else if (HT[i].weight < m2)
			{
				m2 = HT[i].weight;//更新m2的值
				s2 = i;
			}
		}
	}
}
void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,int *w, int n)
{
	//初始化二叉树
	if (n <= 1) return; int m = 2 * n - 1;//n个叶子结点的二叉树有2n-1个结点
	int i; HuffmanTree p = HT;
	HT = (HuffmanTree)malloc((m+1)*sizeof(HTNode));//为哈夫曼树分配存储空间;m+1而非m是因为0号位闲置
	for (p = HT + 1, i = 1; i <= n; ++i, ++p, ++w)
	{
		p->weight = *w;
		p->parent = 0;
		p->lc= 0;
		p->rc = 0;
	}
	for (; i <= m; ++i, ++p)
	{
		p->weight = 0;
		p->parent = 0;
		p->lc= 0;
		p->rc= 0;
	}
    /*等价于for (i = 1; i <= n; ++i)
	{
		HT[i].weight = w[i - 1];
		HT[i].lc = 0;
		HT[i].rc = 0;
		HT[i].parent = 0;
	}
	for (; i <= m; ++i, ++p)
	{
		HT[i].weight =0;
		HT[i].lc = 0;
		HT[i].rc = 0;
		HT[i].parent = 0;
	}*/
	//创建哈夫曼树
	int s1,s2;
	for (i = n + 1; i <= m; i++)
	{
		Select(HT,i-1,s1,s2);
		HT[s1].parent = i;
		HT[s2].parent = i;
		HT[i].lc = s1;
		HT[i].rc = s2;
		HT[i].weight = HT[s1].weight + HT[s2].weight;
	}
	printf("创建哈夫曼树如下\n");
	printf("NUM       weight    parent    lc    rc    \n");
	for (i = 1; i <= m; i++)
	{
		printf("HT[%2d] %6d %6d %6d %6d\n", i, HT[i].weight, HT[i].parent, HT[i].lc, HT[i].rc);
	}
	printf("\n");
	//求哈夫曼编码
	int c,start,f; char* cd;
	HC = (HuffmanCode)malloc((n + 1) * sizeof(char*));
	cd = (char*)malloc(n * sizeof(char)); //cd为临时字符数组
	cd[n - 1] = '\0';
	for (i = 1; i <= n; ++i)
	{
		start = n - 1;
		for (c = i, f = HT[i].parent; f != 0; c = f, f = HT[f].parent)
			if (HT[f].lc == c) cd[--start] = '0';
			else cd[--start] = '1';
		HC[i] = (char*)malloc((n - start) * sizeof(char));
		strcpy_s(HC[i],n-start+1, &cd[start]);
	}
	free(cd);
	printf("哈夫曼编码如下\n");
	for (i = 1; i <= N; i++)
	{
		printf("HT[%d]编码为\n",i);
		puts(HC[i]);
	}
} 
int main(void)
{
	HuffmanTree HT; HuffmanCode HC; int w[N];
	printf("输入叶子结点的值\n"); int i;
	for (i = 0; i < N; i++)
	{
		scanf_s("%d",&w[i]);
	}
	HuffmanCoding(HT,HC, w, N);
	return 0;
}

运行结果

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值