题目描述
对输入的英文大写字母进行统计概率 然后构建哈夫曼树,输出是按照概率降序排序输出Huffman编码。
输入
大写字母个数 n
第一个字母 第二个字母 第三个字母 … 第n个字母。
输出
字母1 出现次数 Huffman编码
字母2 出现次数 Huffman编码
字母3 出现次数 Huffman编码
…
字母n 出现次数 Huffman编码
样例输入
10
I I U U U I U N U U
样例输出
U 6 1
I 3 01
N 1 00
如果大家不了解哈夫曼树是什么,可以看一下这篇博客哈夫曼树
这还有一个视频 视频
哈夫曼树(Huffman Tree)是在叶子结点和权重确定的情况下,带权路径长度最小的二叉树,也被称为最优二叉树。也就是说我们需要将权重大的靠近根结点,权重小的远离根节点
#include <iostream>
#include <stack>
#include <queue>
using namespace std;
struct Node {
char name=' ';
int code[200];
int num = 0;//code的下标
int weight = 0;//权重(次数)
Node* lchild;//左孩子
Node* rchild;//右孩子
Node* parent;
Node* rparent;
Node* lparent;
Node() {}
Node(char c, Node* lc = nullptr, Node* t = nullptr) {
name = c;
lchild = rchild = t;
parent = rparent = lparent = t;
}
Node(int n, Node* lc = nullptr, Node* t = nullptr) {
weight = n;
lchild = rchild = t;
parent = rparent = lparent = t;
}
};
void sort(Node** arr, int n) {//排序
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - 1 - i; j++) {
if (arr[j]->weight <= arr[j + 1]->weight) {
Node* t = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = t;
}
}
}
}
Node* solve(Node** arr, int len) {
Node* parent = nullptr;
while (len != 0) {
sort(arr, len);
Node* first = arr[len-1];
Node* second = arr[len-2];
len -= 2;
parent = new Node(first->weight + second->weight);
parent->lchild = first;
parent->rchild = second;
first->parent = second->parent = parent;
first->rparent = second->lparent = parent;
if (len == 0)
return parent;
arr[len] = parent;
len++;
}
return nullptr;
}
void seekCode(Node* tree, char c) {
queue<Node*> q;
q.push(tree);
while (!q.empty()) {
Node* t = q.front();
q.pop();
if (t->name == c) {//找到
Node* t1 = t;
Node* t2 = t1->parent;
while (t2 != nullptr) {
//判断父子关系
if (t2->lchild == t1 && t1->rparent == t2 ) t->code[t->num] = 0;
else t->code[t->num] = 1;
t->num++;
t1 = t2;
t2 = t1->parent;
}
break;
}
if(t->lchild != nullptr)
q.push(t->lchild);
if(t->rchild != nullptr)
q.push(t->rchild);
}
}
int main() {
int n;
int len = 0;//代表元素的个数
cin >> n;
char c;
Node** arr = new Node*[10000];
Node** temp = new Node*[10000];
//-------------得到每个字母出现的次数
for (int i = 0; i < n; i++) {
cin >> c;
int flag = 0;
for (int j = 0; j < len; j++) {
if (arr[j]->name == c) {
flag = 1;
arr[j]->weight++;
break;
}
}
if (!flag) {
arr[len] = new Node(c);
arr[len]->weight++;
len++;
}
}
//---------------备用
sort(arr, len);
for (int i = 0; i < len; i++)
temp[i] = arr[i];
//----------------构建哈夫曼树
Node* tree = solve(arr, len);
for (int i = 0; i < len; i++)
seekCode(tree, temp[i]->name);
for (int i = 0; i < len; i++) {
cout << temp[i]->name << " " << temp[i]->weight << " ";
for (int j = temp[i]->num-1 ; j >= 0; j--)
cout << temp[i]->code[j];
cout << endl;
}
}
上面的程序纯原创,我个人感觉写的比较复杂,但感觉写的挺直白(hh),大家有更好的想法,欢迎评论留言