数据结构---霍夫曼编码

霍夫曼编码算法的实现

从键盘输入字符序列及对应的权重,输出霍夫编码

分析:

  • 构造树结点,输入带编码字符及对应的权值;
  • 在树结点中选择parent = 0, 且权值最小的两个结点
  • 构造Huffman树并求出编码

代码:


#include "pch.h"
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

#define N 10 //树中叶子结点的最大数目
#define M (2*N-1)//树中结点的最大数目

typedef struct Node
{
	int weight;//权重
	int parent, lchild, rchild;//左右孩子及双亲

} HTNode;

typedef struct 
{
	char data;// 字符
	int weight; //权重
	char code[N];//编码
}HTCode;


void Init(HTCode * ht, int *n)
//初始化,从键盘读入n个字符及权值
{
	int i;
	printf("请输入带编码字符的个数:\n");
	scanf_s("%d",&(*n));
	rewind(stdin);
	printf("请输入带编码的字符:\n");
	for (i = 0; i < (*n); i++)
	{
		scanf_s("%c", &(ht[i].data));
	}
	rewind(stdin);
	printf("请输入带编码字符的权值:\n");
	for (i = 0; i < (*n); i++)
	{
		scanf_s("%d", &(ht[i].weight));
	}
	rewind(stdin);//清空缓冲区

}


void Select(HTNode *ht, int *s1, int *s2, int k)
/*从ht[0,1,2,...,k]结点中选择权值最小且parent=0的两个结点*/
{
	
	int i;
	for (i = 0; i < k; i++)
	{
		if (ht[i].parent == 0)
			break;
	}
	(*s1) = i;//找到第一个parent为零的点
	for (i = (*s1)+1; i < k; i++)
	{
		if (ht[i].parent == 0 && ht[i].weight < ht[(*s1)].weight)
		{
			(*s1) = i;
		}
	}
	for (i = 0; i < k; i++)
	{
		if (ht[i].parent == 0 && i != (*s1))
			break;
	}
	(*s2) = i;
	for (i = (*s2) + 1; i < k; i++)
	{
		if (ht[i].parent == 0 && i != (*s1) && ht[i].weight < ht[(*s2)].weight)
			(*s2) = i;
	}

}

void HuffmanCoding(HTNode *ht, HTCode *hc, int n)
/*构建霍夫曼树,并进行霍夫曼编码*/
{
	int s1, s2;
	int c, f;
	int Num_TreeNode = 2 * n - 1;// 总的结点数目
	int i;
	char code[N];
	int start;
	/*构建霍夫曼树*/
	for (i = 0; i < Num_TreeNode; i++) 
	{
		if(i<n)//前n个叶子结点
			ht[i].weight = hc[i].weight;
		ht[i].parent = 0;
		ht[i].rchild = ht[i].lchild = 0;	
	}
	for (i = n; i < Num_TreeNode; i++)
	{
		Select(ht, &s1, &s2, i );//从前n个结点中选择两个权值最小的结点
		ht[s1].parent =i;
		ht[s2].parent = i;
		ht[i].lchild = s1;
		ht[i].rchild = s2;
		ht[i].parent = 0;
		ht[i].weight = ht[s1].weight + ht[s2].weight;
	}
	/*进行霍夫编码,从叶子结点到根结点*/
	code[n] = '\0';
	for (i = 0; i < n; i++)
	{
		start = n ;
		for (c = i, f = ht[i].parent; f; c = f, f = ht[c].parent)//沿着叶子向根走
		{
			if (c == ht[f].lchild)
				code[--start] = '0';
			else 
				code[--start] = '1';
		}
		strcpy_s(hc[i].code, &code[start]);
	}
	
}

int main()
{
	HTNode ht[M+1];
	HTCode hc[N+1];
	int n;// 叶子结点个数
	Init(hc, &n);//初始化
	HuffmanCoding(ht, hc, n);
	int i;
	for (i = 0; i < n; i++)
	{
		printf("%c-----%s\n", hc[i].data, hc[i].code);
	}
	return 0;
}

程序运行截图:
在这里插入图片描述

哈夫曼编码(Huffman Coding)是一种编码方式,哈夫曼编码是可变字长编码(VLC)的一种。 Huffman于1952年提出一种编码方法,该方法完全依据字符出现概率来构造异字头的平均长 度最短的码字,有时称之为最佳编码,一般就叫作Huffman编码。 以哈夫曼树─即最优二叉树,带权路径长度最小的二叉树,经常应用于数据压缩。 在计算机信息处理中,“哈夫曼编码”是一种一致性编码法(又称"熵编码法"),用于数据的无损耗压缩。这一术语是指使用一张特殊的编码表将源字符(例如某文件中的一个符号)进行编码。这张编码表的特殊之处在于,它是根据每一个源字符出现的估算概率而建立起来的(出现概率高的字符使用较短的编码,反之出现概率低的则使用较长的编码,这便使编码之后的字符串的平均期望长度降低,从而达到无损压缩数据的目的)。这种方法是由David.A.Huffman发展起来的。 例如,在英文中,e的出现概率很高,而z的出现概率则最低。当利用哈夫曼编码对一篇英文进行压缩时,e极有可能用一个位(bit)来表示,而z则可能花去25个位(不是26)。用普通的表示方法时,每个英文字母均占用一个字节(byte),即8个位。二者相比,e使用了一般编码的1/8的长度,z则使用了3倍多。倘若我们能实现对于英文中各个字母出现概率的较准确的估算,就可以大幅度提高无损压缩的比例。 <br>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

XIE_QAID

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

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

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

打赏作者

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

抵扣说明:

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

余额充值