题目内容
对于给定的一组字符,可以统计字符出现的频率,然后根据其出现的频率进行哈夫曼编码,并能输出对应的哈夫曼树和哈夫曼编码;实现哈夫曼解码。
输入和输出
输入
字符长度
一组字符
01字符长度
一组01字符
例子
100
gggaaaaahhhhhhhhhhhfffffffffffffffffffffffbbbbbbbbbbbbbbbbbbbbbbbbbbbbbeeeeeeeeeeeeeecccccccdddddddd
2
10
输出
各个字符对应的哈夫曼编码
输入的字符对应的哈夫曼编码
哈夫曼树
01字符对应的字符
例子
a 0001
b 10
c 1110
d 1111
e 110
f 01
g 0000
h 001
0000000000000001000100010001000100100100100100100100100100100100101010101010101010101010101010101010101010101011010101010101010101010101010101010101010101010101010101010110110110110110110110110110110110110110110111011101110111011101110111011111111111111111111111111111111
输出哈夫曼树
下标 权值 父结点 左孩子 右孩子 结点
0 3 8 -1 -1 g
1 5 8 -1 -1 a
2 11 10 -1 -1 h
3 23 12 -1 -1 f
4 29 13 -1 -1 b
5 14 11 -1 -1 e
6 7 9 -1 -1 c
7 8 9 -1 -1 d
8 8 10 0 1
9 15 11 6 7
10 19 12 8 2
11 29 13 5 9
12 42 14 10 3
13 58 14 4 11
14 100 -1 12 13
b
代码
#include <iostream>
#include <algorithm>
#include <map>
#include<vector>
using namespace std;
struct HTNode
{
char data; //代表字母
int weight; //权值
int parent, lchild, rchild; //双亲和孩子
HTNode()
{
weight = parent = lchild = rchild = -1; //初始化为-1
}
};
int len; //代表输入字符的长度(个数)
int n = 0; //代表输入字符的种类
//vector<HTNode*> arr;
HTNode *arr;//用来存放二叉树
map<char, string> mp;//存放字符和字符对应的哈夫曼编码
string str; //暂时存放生成的哈夫曼编码
char *char_huffman; //存放输入的元素
string *str_huffman; //存放输入元素最终的哈夫曼编码
char *a; //存放传入的二进制编码
char *b; //存放译出的字符
void CreateHuffmanTree()
{ //生成哈夫曼树
for (int i = n; i < 2 * n - 1; i++)
{
int min1 = 65522; int min2 = min1;//min1第一小,min2第二小
int x1 = -1, x2 = -1;//分别记录两者下标
for (int j = 0; j < i; j++)
{
if (arr[j].parent == -1)
{
if (arr[j].weight < min1)
{
min2 = min1;
x2 = x1;
min1 = arr[j].weight;
x1 = j;
}
else if (arr[j].weight < min2)
{
min2 = arr[j].weight;
x2 = j;
}
}
}
arr[x1].parent = arr[x2].parent = i;
arr[i].weight = min1 + min2;
arr[i].lchild = x1;
arr[i].rchild = x2;
}
}
//哈夫曼编码
void HaffmanCode()
{
for (int i = 0; i < n; i++)
{
int t = i; //代表儿子
str = "";
int parent = arr[i].parent;
for (int j = parent; j != -1; t = j, j = arr[j].parent)
{
if (arr[j].lchild == t)
{
str += '0';
}
else
{
str += '1';
}
}
reverse(str.begin(), str.end());
mp[arr[i].data] = str;
}
}
//哈夫曼译码
void HaffmanDecode(int q,int &k)
{
for (int i = 0; a[i] != '\0'; i++){
if (a[i] == '0')
{
q = arr[q].lchild;
}
else if (a[i] == '1')
{
q = arr[q].rchild;
}
if (arr[q].lchild == -1 && arr[q].rchild == -1)
{
b[k++] = arr[q].data;
q = 2 * n - 2;
}
}
b[k] = '\0';
}
int main()
{
freopen("in.txt", "r", stdin);
char c; //带输入的字符
cin >> len;
char_huffman = new char[len];
str_huffman = new string[len];
arr = new HTNode[2 * len - 1];//此时未得出字母类型,只能用len来建立数组
getchar();//去掉回车符
for (int i = 0; i < len; i++)
{
cin >> c;
//scanf(" %c", &c);
char_huffman[i] = c;
int flag = 0;
for (int j = 0; j < n; j++)
{
if (arr[j].data == c)
{
flag = 1;
arr[j].weight++;
break;
}
}
if (!flag)
{
arr[n].data = c;
arr[n].weight = 1;
n++;
}
}
/*用来测试上述代码
for (int i = 0; i < n; i++)
{
cout << arr[i].data << " : ";
cout << arr[i].weight << endl;
}
*/
int q = 2 * n - 2; //初始化为根结点的下标
int k = 0; //记录译出字符数组的下标
int len2;
char d;
cin >> len2;
a = new char[len2]; //存放二进制代码
b = new char[len2]; //存放二进制代码译出的字符
getchar();//去掉回车符
for (int i = 0; i < len2; i++)
{
cin >> d;
a[i] = d;
}
CreateHuffmanTree();
HaffmanCode();
HaffmanDecode(q,k);
for (auto p : mp)
{
cout << p.first << " " << p.second << endl;
}
for (int i = 0; i < len; i++)
{
str_huffman[i] = mp[char_huffman[i]];
}
for (int i = 0; i < len; i++)//输出输入的所有元素的哈夫曼编码
{
cout << str_huffman[i];
}
cout<<endl;
//输出哈夫曼树
cout<<"输出哈夫曼树"<<endl;
cout<<"下标"<<" 权值"<<" 父结点"<<" 左孩子"<<" 右孩子"<<" 结点"<<endl;
for(int i=0;i<2*n-1;i++){
cout<<i<<" "<<arr[i].weight<<" "<<arr[i].parent<<" "<<arr[i].lchild<<" "<<arr[i].rchild<<" "<<arr[i].data<<endl;
}
//输出二进制代码转换成的字符
for(int i=0;i<k;i++){
cout<<b[i]<<" ";
}
return 0;
}