哈夫曼树
请为下面这段英文文本构造哈夫曼编码:
“Effificient and robust facial landmark localisation is crucial for the deployment of
real-time face analysis systems. This paper presents a new loss function, namely
Rectifified Wing (RWing) loss, for regression-based facial landmark localisation with
Convolutional Neural Networks (CNNs). We fifirst systemically analyse different loss
functions, including L2, L1 and smooth L1. The analysis suggests that the training of
a network should pay more attention to small-medium errors. Motivated by this
finding, we design a piece-wise loss that amplififies the impact of the samples with
small-medium errors. Besides, we rectify the loss function for very small errors to
mitigate the impact of inaccuracy of manual annotation
1. 请计算出每个字符出现的概率,并以概率为权重来构造哈夫曼树,写出构造 过程、画出最终的哈夫曼树,得到每个字符的哈夫曼编码。
- 哈夫曼编码:
字母 | 次数 |
---|---|
2 | 1 |
B | 1 |
E | 1 |
M | 2 |
( | 2 |
) | 2 |
1 | 2 |
C | 2 |
R | 2 |
T | 2 |
L | 3 |
W | 3 |
b | 3 |
v | 3 |
N | 4 |
K | 4 |
- | 5 |
. | 5 |
, | 6 |
w | 8 |
g | 10 |
p | 10 |
y | 13 |
u | 14 |
h | 15 |
d | 16 |
c | 21 |
m | 22 |
f | 27 |
r | 31 |
l | 36 |
n | 41 |
o | 41 |
t | 48 |
a | 52 |
s | 53 |
e | 54 |
i | 56 |
104 |
- 构造过程:
①. 从出现次数组成的数列中,找出最小的两个数,将他们两个的和加入到数列中重新排序。两个数及他们的和共同组成一个二叉树。
②. 重复过程1,最终数列中只剩1个值,最终的二叉树就是哈夫曼树。 - 哈夫曼树图:
2. 请将上述设计哈夫曼编码的过程,用代码来实现,并输出各个字母的哈夫曼 编码。(有代码,有运行结果的截图)
- Code:
#include <iostream>
#include <map>
#include <string>
#include <cstdlib>
#include <vector>
using namespace std;
struct Huffmantree {
int weight;
int parent;
int lchild;
int rchild;
};
void CreateHuffmanCode(Huffmantree* ht, vector<string>& hc, int index, int p);
void select(Huffmantree*& ht, int i, int& s1, int& s2);
void CreatHuffmantree(Huffmantree*& ht, int n, map<char, int>number);
int main() {
std::ios::sync_with_stdio(false);
map<char, int> number;
string data;
vector<char> res;
getline(cin, data);
for (auto element : data)
number[element]++;
cout << "字符统计:" << endl;
res.emplace_back(' ');
for (auto element : number) {
cout << "字符" << element.first << " " << "概率:" << element.second << endl;
res.emplace_back(element.first);
}
Huffmantree* tree;
CreatHuffmantree(tree, number.size(), number);
vector<string> hc(number.size() + 1, "");
cout << endl << "哈夫曼编码:" << endl;
for (int i = 1; i <= number.size(); i++){
CreateHuffmanCode(tree, hc, i, i);
cout << res[i] << ":" << hc[i] << endl;
}
}
void select(Huffmantree*& ht, int t, int& s1, int& s2){
int j = 1;
while (ht[j].parent != 0) j++;
s1 = j;
for (int i = 1; i <= t; i++){
if (ht[i].parent == 0 && ht[i].weight <= ht[s1].weight)
{
s1 = i;
}
}
j = 1;
while (ht[j].parent != 0 || j == s1) j++;
s2 = j;
for (int i = 1; i <= t; ++i){
if (ht[i].parent == 0 && ht[i].weight <= ht[s2].weight && i != s1){
s2 = i;
}
}
}
void CreatHuffmantree(Huffmantree*& ht, int n, map<char, int>number){
if (n <= 1)
return;
int m = 2 * n - 1;
int s1;
int s2;
ht = new Huffmantree[m + 1];
for (int i = 1; i <= m; i++)
ht[i].parent = ht[i].lchild = ht[i].rchild = 0;
int i = 1;
for (auto element : number){
ht[i].weight = element.second;
i++;
}
for (i = n + 1; i <= m; i++){
select(ht, i - 1, s1, s2);
ht[s1].parent = ht[s2].parent = i;
ht[i].lchild = s1;
ht[i].rchild = s2;
ht[i].weight = ht[s1].weight + ht[s2].weight;
}
}
void CreateHuffmanCode(Huffmantree* ht, vector<string>& hc, int index, int p){
while (ht[p].parent != 0){
int temp = ht[p].parent;
if (ht[temp].lchild == p) hc[index].insert(hc[index].begin(), '0');
else if (ht[temp].rchild == p) hc[index].insert(hc[index].begin(), '1');
p = ht[p].parent;
}
}
3. 请分析算法的效率,至少包括时间复杂度和空间复杂度等。
- 时间复杂度:O(n*logn)
- 空间复杂度:O(n)