Huffman树——用法解析

基本介绍:

H u f f m a n Huffman Huffman树是一种树结构,它的出现是为了解决根据字符出现频率对字符进行“不等长编码”的问题,提高编码效率。“不等长编码”需要满足任何一个字符的编码不能是另外一个字符编码的前缀,否则将产生二义性。为了使最终的编码长度最短,所以出现了 H u f f m a n Huffman Huffman树。

性质特点(以二叉 H u f f m a n Huffman Huffman树为例):

1.树的叶子节点表示字符,节点的权值表示字符在字符串中出现的次数。
2.二叉树的左右分支的边分别表示 0 0 0 1 1 1,最终某个字符的编码就是根节点到叶子节点的路径。(原理同字典树)
3.对于带权二叉树,某节点的带权路径长度为 w [ i ] × l [ i ] w[i] \times l[i] w[i]×l[i] w [ i ] w[i] w[i]表示权值, l [ i ] l[i] l[i]表示路径长度。其带权路径长度定义为树中所有叶节点的带权路径长度之和,即 ∑ w [ i ] × l [ i ] \sum w[i] \times l[i] w[i]×l[i]
4.所以最终经过编码的字符串的长度就是带权二叉树的带权路径长度即 ∑ w [ i ] × l [ i ] \sum w[i] \times l[i] w[i]×l[i]
5.可以证明当二叉树是一棵完全二叉树的时候带权二叉树的带权路径长度最小,对于 H u f f m a n Huffman Huffman树,即经过 H u f f m a n Huffman Huffman树编码的字符串长度最小。

构造方法:

1.根据给定的 n n n w [ i ] w[i] w[i],构造 n n n个二叉树的集合,其中每棵二叉树只含一个权值为 w [ i ] w[i] w[i]的根节点,其左、右子树为空树。
2.在所有二叉树中选择根节点权值最小的两棵二叉树,分别作为左、右子树构造一个新的二叉树,新二叉树的根节点权值即为其左、右子树根节点的权值之和。
3.从二叉树集合中删去,并加入刚生成的新树。
4.重复过程 2 2 2 3 3 3,直到集合中只剩一棵树。

核心代码:

typedef long long ll;
const ll maxn=100010;
struct node
{
	ll data;
	ll lchild,rchild;
	ll pos;
	bool operator>(const node a)const
	{
		return data>a.data;
	}
}tree[maxn],num[maxn];
priority_queue<node,vector<node>,greater<node> > q;//利用优先队列维护一个data递增的序列
ll w[maxn];
void createhuffmantree(ll n)
{
	for(ll i=1;i<=n;i++)//初始化
	{
		tree[i].pos=i;
		tree[i].data=w[i];
		tree[i].lchild=tree[i].rchild=0;
		q.push(tree[i]);
	}
	ll t=n;//可用的位置
	for(ll i=2;i<=n;i++)
	{
		node x,y;
		x=q.top();q.pop();
		y=q.top();q.pop();
		++t;
		//构造新树
		tree[t].data=x.data+y.data;
		tree[t].pos=t;
		tree[t].lchild=x.pos;
		tree[t].rchild=y.pos;
		q.push(tree[t]); 
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值