最优前缀码 哈夫曼编码
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)