写的比较低效丑陋,欢迎各路大佬纠错(估计大佬们应该也没有这给闲情逸致看我丑陋的代码)。
/*
* 主题:堆优化的哈夫曼树
* 作者:GGN_2015
* 备注:我想封装一下,但是考虑到还没学 oop,我就不封装了
*/
#include <iostream> /// 用于数据的输入输出
#include <queue> /// 使用 priority_queue 优化哈夫曼树构建
#include <string> /// 使用 string 记录各种符号以及其编码
#include <map> /// 使用 map 记录符号与编码的对应关系
#include <vector> /// 优先队列的容器
using namespace std;
const int maxn = 100000 + 6; /// 二叉树的结点数上限
struct TreeNode { /// 哈夫曼树中的结点
string C;
int T;
int lch, rch; /// 记录二叉树左右子对应的下标(静态链表)
} tree[maxn];
int ncnt; /// 二叉树中当前的结点个数
struct Compare { /// 比较函子
bool operator()(int A, int B) {
return tree[A].T > tree[B].T; /// 如此可诱导生成小根堆
}
};
priority_queue<int, vector<int>, Compare> heap;
void inputData(); /// 输入代编码的数据
void buildTree(); /// 构建哈夫曼树
void outputCode(); /// 输出每种符号对应的编码
int insertHeap(string, int); /// 向优先队列中插入数据
void matchCode(int, string); /// 深搜哈夫曼树,将编码与符号对应起来
int main() {
inputData(); /// 输入待编码的数据
buildTree(); /// 构建哈夫曼树
outputCode(); /// 输出每种符号的编码
return 0;
}
void inputData() {
int n;
cin >> n; /// 输入符号总数
for(int i = 1; i <= n; i ++) {
string C;
int T;
cin >> C >> T; /// 输入 C T 表示符号 C 在文中出现了 T 次
insertHeap(C, T); /// 将该数据插入堆中
}
}
int insertHeap(string C, int T) {
int id = ++ ncnt;
tree[id] = (TreeNode){C, T, 0, 0}; /// 在树上新插入一个结点
heap.push(id);
return id;
}
int root; /// 哈夫曼树的树根编号
map<string, string> codeDic; /// 用来储存每种符号对应的哈夫曼编码
void buildTree() {
while(heap.size() > 1) { /// 进行合并操作
int L = heap.top(); heap.pop();
int R = heap.top(); heap.pop();
int newnode = insertHeap("", tree[L].T + tree[R].T);
tree[newnode].lch = L;
tree[newnode].rch = R;
}
root = heap.top(); heap.pop();
matchCode(root, ""); /// 将编码与符号对应起来
}
void matchCode(int x, string code) {
if(tree[x].lch) matchCode(tree[x].lch, code + "0");
if(tree[x].rch) matchCode(tree[x].rch, code + "1"); /// 在左子树与右子树递归
if(tree[x].C != "") codeDic[tree[x].C] = code; /// 记录编码
}
void outputCode() {
typedef map<string, string> :: iterator ITR; /// 枚举 map 中的所有元素
for(ITR itr = codeDic.begin(); itr != codeDic.end(); itr ++) {
cout << "codeDic[" << itr -> first << "]= " << itr -> second << endl; /// 输出对应的编码
}
}