最优前缀码

最优前缀码 哈夫曼编码

1、问题

在这里插入图片描述

2、解析

  • 最优二元前缀码:每个码字平均使用二进制位数最小的前缀码。

  • 哈夫曼算法:构造最优前缀码的贪心算法

  • 哈夫曼过程:

      - 第一步:以每个结点作为根,构造只有一个根结点的n棵二叉树,根的权值就是结点的权。
      - 第二步:在所有二叉树中选择根的权值最小的两棵二叉树作为左右子树构造一棵新的二叉树,根的权值等于其左右子树的根的权值之和。
      - 第三步:去掉选中的二叉树、加入新生成的二叉树。
      - 第四步:重复2、3步,直至只剩下一棵树为止。  
    
  • 哈夫曼编码
    在这里插入图片描述

实例:有a、b、c、d、e,f 6个字符,它们的权值分别为5,1,3,7,2,10
在这里插入图片描述

3、设计

#include<bits/stdc++.h>
const int T = 1000;
using namespace std;
string str;
int a,h[T];
string haf[T];

struct BNode {
	int value,id;
	bool friend operator<(const BNode &m,const BNode &n) {
		if (m.value!=n.value) 
		    return m.value>n.value;
		return m.id>n.id;
	}
};
struct Btree {
	int left;
	int right;
	int value;
}t[T];
priority_queue<BNode>f;

void fetch() {
	for (int i=1;i<=a;i++) {
		string g;
		int f = i;
		while (h[f]) {
			g = (f==t[h[f]].left?'0':'1')+g;
			f = h[f];
		}
		haf[i] = g;
	}
}
void Haf() {
	for (int i=1;i<a;i++) {	
	    int id = i+a;	
		BNode n = f.top();
		f.pop();
		BNode m = f.top();
		f.pop();
	    int value = n.value+m.value;
		t[id].left = n.id;
		t[id].right = m.id;
		t[id].value = value;
		h[n.id] = id;
		h[m.id] = id;
		f.push({value,id});
	}
	fetch();
}
int main() {
	cout<<"请输入表示各个节点的字符串:"<<endl; 
	cin>>str;
	a = str.length();
    cout<<"请依次输入各个节点的权重:"<<endl; 
	for (int i=1;i<=a;i++) {
		int value;
		cin>>value;
		f.push({value,i});
	}
	Haf();
	cout<<"哈夫曼编码为:\n"; 
	for (int i=1;i<=a;i++) {
		cout<<str[i-1]<<":";
		cout<<haf[i]<<endl;
	}
	return 0;
}
/*
abcdef
5 1 3 7 2 10
*/

4、分析

O(nlogn)频率排序;for循环O(n),插入操作O(logn),算法时间复杂度是O(nlogn)

5、源码

哈夫曼编码 最优前缀码

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值