字符出现次数的哈夫曼树
分析和代码
/**
给定数组vector<pair<char, int>>,其中pair的first是字符,second是字符出现的次数
请构造哈夫曼树?
思路:
1:构建以字符出现的次数为key的优先队列【最小堆哦】
2:将数组vector<pair<char, int>>加入到优先队列中
3:每次从优先队列弹出两个元素,构建以两个key的和为根、两个key为孩子的二叉树,然后将两个key的和加入到优先队列中
4:重复3直到优先队列中只有一个元素
优先队列:
priority_queue<pair<int, HuffmnNode*>, vector<pair<int, HuffmnNode*>>, Comp>
其中:
pair的int为字符出现的次数,
HuffmnNode为哈夫曼树的节点
struct HuffmnNode{
char ch; //字符,非叶子节点用' '代替
int value; //字符出现的次数【也可以看成是权值】
struct HuffmnNode* left; //树的左孩子
struct HuffmnNode* right; //树的右孩子
};
vector<pair<int, HuffmnNode*>>是优先队列使用的容器
Comp是比较器【仿函数】
Huffman:
HuffmnNode* m_root; //树的根节点
unordered_map<char, string> m_char_to_encode; //字符到密文的hash表
*/
class Huffman{
private:
//哈夫曼树的节点
struct HuffmnNode{
HuffmnNode(char ch, int value){
this->ch = ch;
this->value = value;
left = nullptr;
right = nullptr;
}
char ch;
int value;
struct HuffmnNode* left;
struct HuffmnNode* right;
};
public:
//优先队列的比较器
struct Comp{
bool operator()(const pair<int, HuffmnNode*>& x, const pair<int, HuffmnNode*>& y){
return x.first > y.first;
}
};
//构造哈夫曼树
void generate_huffman(vector<pair<char, int>>& v){
priority_queue<pair<int, HuffmnNode*>, vector<pair<int, HuffmnNode*>>, Comp> pq;
//将数组vector加入到优先队列中
for (auto& data : v){
HuffmnNode* temp = new HuffmnNode(data.first, data.second);
pq.push(make_pair(data.second, temp));
}
//构造树
while (pq.size() != 1){
//弹出来
auto tp1 = pq.top(); pq.pop();
auto tp2 = pq.top(); pq.pop();
//构造树
HuffmnNode* temp = new HuffmnNode(' ', tp1.first + tp2.first);
temp->left = tp1.second;
temp->right = tp2.second;
//再加进去
pq.push(make_pair(tp1.first + tp2.first, temp));
}
//树根
m_root = pq.top().second;
generate_encode(m_root,string(""));
}
//根据哈夫曼树生成密文
void generate_encode(HuffmnNode* head,string& str){
if (head->left == nullptr && head->right == nullptr){
m_char_to_encode.insert(make_pair(head->ch, str));
return;
}
if (head->left != nullptr){
str.push_back('0');
generate_encode(head->left, str);
str.pop_back();
}
if (head->right != nullptr){
str.push_back('1');
generate_encode(head->right, str);
str.pop_back();
}
}
//加密
string encode(string& str){
string ret;
for (auto ch : str){
ret += m_char_to_encode[ch];
}
return ret;
}
//解密
string decode(string& encode){
string ret;
for (size_t i = 0; i < encode.size(); /*++i*/){
HuffmnNode* temp = m_root;
while (temp->left != nullptr && temp->right != nullptr){
temp = encode[i] == '0' ? temp->left : temp = temp->right;
++i;
}
ret.push_back(temp->ch);
}
return ret;
}
private:
HuffmnNode* m_root;
unordered_map<char, string> m_char_to_encode;
};
思考
1、没有写析构函数释放资源
2、decode有好的实现方法吗?