贪心算法(求解最优化问题)及其应用赫夫曼编码

1、贪心算法求解流程:
通常自顶向下设计:做出一个选择(做局部最优选择),然后求解剩下的那个与原问题类似的子问题。
在这里插入图片描述
2、贪心算法设计步骤:
在这里插入图片描述
3、0-1揹包问题与分数揹包问题:
0-1揹包问题:【动态规划】01揹包问题(通俗易懂,超基础讲解)
分数揹包问题:贪心算法,见算法导论16.2节

4、赫夫曼编码: 目标:字符出现频率高,使其二进制位数少
对于字符等数据,根据其出现频率,通过赫夫曼贪心算法构造出字符的最优前缀码(二进制表示),从而降低所占空间。
前缀码:没有任何码字是其他码字的前缀。
最优前缀码对应的树有N个叶节点(字符个数),且恰有N-1个内部节点。

4.1、赫夫曼二进制编码构造流程:
a)算法自底向上构造对应最优编码的二叉树T,从N个叶节点开始,执行N-1次合并操作创建最终二叉树。
b)算法使用字符出现频率为关键字的最小优先队列Q,以识别两个最低频率的对象将其合并,
c)合并两对象时得到的新对象频率设置为两原对象频率之和。
流程图如下:
在这里插入图片描述
4.2、赫夫曼二进制编码构造C++代码:
假设给定字符及其出现频率组成结构的数组nodeArr

#include <queue>
struct node{
	int num; // 字符出现频率
	char c; //字符
	node* left;
	node* right;
	node(int x,char y):num(x),c(y),left(null),right(null){}
	node():num(0),c('0'),left(null),right(null){}
	bool operator< (const node& a){
		return num>a.num; //从小到大排列
	}
}
node* nodeArr[10]; // 假设已经给定,且存储在动态内存

priority_queue<node*> q; // 按字符出现频率由小到大排列
for(int i = 0;i<10;i++){
	q.push(nodeArr[i]);
}
for(int i = 0;i<9;i++){ // 10个节点9条边
	node* z = new node;
	node* tmp1 = q.front();
	q.pop();
	node* tmp2 = q.front();
	q.pop();
	z->left = tmp1;
	z->right = tmp2;
	z->num = tmp1->num +tmp2->num;
	q.push(z);
}
node* root =  q.front(); //树的根节点

总结:

1、在构造哈夫曼编码过程中,频率低的放左节点,高的放右节点。
2、哈夫曼编码通过将出现频率高的字符用少数二进制位表示,从而降低使用空间,实现压缩编码。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章