【数据结构】哈夫曼编码

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

typedef struct{
	unsigned int weight;		//权值
	unsigned int parent , lchild , rchild;		//父节点,左子树,右子树
}HTNode, *HuffmanTree;			//动态分配数组存储赫夫曼树

typedef char ** HuffmanCode;	//动态分配数组存储赫夫曼编码表

unsigned int min1,min2;

void Select(HuffmanTree &HT,int i,int &s1,int &s2)
{
	min1=min2=32767;
	s1=s2=0;
	int j;
	for(j=1;j<=i;j++)
	{
		if(HT[j].weight<min1&&!HT[j].parent)
		{
			min2=min1;
			s2=s1;
			min1=HT[j].weight;
			s1=j;
		}
		else if(HT[j].weight<min2&&!HT[j].parent)
		{
			min2=HT[j].weight;
			s2=j;
		}
	}
}
void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,int *w,int n){
	//w存放n个字符的权值,构造赫夫曼树HT,并求出n个字符的赫夫曼编码HC
	int m;//m表示赫夫曼树总共结点
	int i;
	int s1=0;
	int s2=0;
	HuffmanTree p;
	char *cd;
	unsigned int start,c,f;
	if(n<=1)
		return;
	m = 2*n -1 ;	//节点数
	HT = (HuffmanTree)malloc((m+1)*sizeof(HTNode));	//分配存储空间,0号单元未用
	for(p = HT+1,i=1;i<=n;++i,++p){
		p->weight = w[i];
		p->parent = 0;
		p->lchild = 0;
		p->rchild = 0;
	}
	for(i=n+1;i<=m;++i,++p){
		p->weight = 0;
		p->parent = 0;
		p->lchild = 0;
		p->rchild = 0;
	}
		
	for(i=n+1;i<=m;++i){		//建赫夫曼树
		//在HT[1...i-1]选择parent为0且weight最小的两个结点,其序号分别为是s1和s2
		Select(HT,i-1,s1,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<=m;i++)
		printf("%d,%d,%d,%d\n",HT[i].weight,HT[i].parent,HT[i].lchild,HT[i].rchild);
	//从叶子到根逆向求每个字符的赫夫曼编码
	HC = (HuffmanCode)malloc((n+1)*sizeof(char *));	//分配n个字符编码的头指针向量
	cd = (char *)malloc(n*sizeof(char));			//分配求编码的工作空间
	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].lchild == c)
				cd[--start] = '0';
			else
				cd[--start] = '1';
		HC[i] = (char *)malloc((n-start)*sizeof(char));
		strcpy(HC[i],&cd[start]);		//
	}
	free(cd);
}
void main(){
	int n;
	int NT[100];
	int i;
	HuffmanTree HT;
	HuffmanCode HC;
	printf("请输入你的赫夫曼树的叶子结点个数:\n\n");
	scanf("%d",&n);
	for(i=1;i<=n;i++)
	{
		printf("输入第 %d 个数字的权重",i);
		scanf("%d",&NT[i]);
	}
	HuffmanCoding(HT,HC,NT,n);
	printf("赫夫曼树编码如下:\n\n");
	for(i=1;i<=n;i++)
	{
		printf("%d :%s\n",HT[i].weight,HC[i]);
	}
	printf("\n\n");
}



By Mr.Z

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
哈夫曼编码是一种用于数据压缩的方法,它基于字符出现频率来构建最优的编码表。下面是哈夫曼编码的译码和编码过程: 1. 哈夫曼编码: - 统计字符出现频率,并根据频率构建哈夫曼树。频率较高的字符位于树的较低层。 - 通过从根到叶子节点的路径上的0和1来表示字符,构建编码表。 - 使用编码表将输入文本的字符替换为对应的哈夫曼编码。 2. 哈夫曼译码: - 使用相同的哈夫曼树和编码表,读取编码后的二进制数据。 - 从根节点开始,按照读取到的0或1依次向左或向右移动,直到达到叶子节点。每次到达叶子节点后,输出对应的字符,并重新回到根节点继续读取。 下面是一个示例,展示如何使用哈夫曼编码和译码来进行数据压缩和解压缩: 假设我们有以下文本:C知道 编程是很有趣的! 1. 统计字符频率并构建哈夫曼树: 字符频率:{空格: 4, C: 2, 知: 2, !: 1, 程: 1, 译: 1, 是: 1, 有: 1, 趣: 1, 的: 1, 编: 1, 码: 1} 构建的哈夫曼树如下: [11] / \ / \ / \ / \ / \ / \ / \ C 知 ␣ ! 程 译 \ \ / \ 是 有 \ \ \ / \ 趣 的 构建的编码表如下: C: 00 知: 01 ␣: 100 !: 1010 程: 1011 译: 1100 是: 11010 有: 11011 趣: 11100 的: 11110 编: 111110 码: 111111 2. 编码: 将输入文本的字符替换为对应的哈夫曼编码,得到编码后的二进制数据:00 01 100 111110 1011 1100 11010 11011 11100! 3. 解码: 根据相同的哈夫曼树和编码表,读取编码后的二进制数据进行译码,得到原始文本:C知道 编程是很有趣的!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值