对于给定的文本内容,要求采用哈夫曼编码并输出编码后的内容。文本内容由英文字母构成,这里约定不区分字母的大小写。注意,这里约定构造哈夫曼树时,任一结点的左孩子权值不大于右孩子权值,哈夫曼编码时,左分支写'0'右分支写'1';若两个字母的权值相等,则字典序小的字母优先;对于相等的权值,按出现的先后顺序处理。
例如,对于样例1,因不区分大小写,若按大写字母处理,则字母A、B、C、D的出现次数为4、1、2、1,则B对应的1为左孩子,D对应的1为右孩子,得到的父结点权值为2,比原有的2晚出现,因此原来的2为左孩子,新得到的2作为右孩子,对于两个权值4也类似处理。构造所得的哈夫曼树如下图所示。
输入格式:
测试数据有多组,处理到文件尾。每组测试数据在一行上输入一个字符串(仅由大小写英文字母构成且长度不超过360,至少包含2种字母)表示文本内容。
输出格式:
对于每组测试数据,输出哈夫曼编码后的内容。
输入样例:
AcBDaCAA
eAbCDaAAA
输出样例:
01011011101000
01110000010101111
#include<bits/stdc++.h>
using namespace std;
int n;//节点个数
struct Weight {
int weight = 0;
char ch;
};
//Weight num[26];//储存初始数据的权重
struct hufnode {
int quan;//节点权重
int parent, left, right;
int where;//作为左子树还是右子树
int time;//出现次数
char val;//储存的字符是谁
};
//hufnode tree[1000];//整个哈夫曼树
void creattree(Weight num[],hufnode tree[])
{
int m1, m2;
int x1, x2;
int j = 0, i = 0;
for (i = 0; i < 2 * n - 1; i++)//初始化
{
tree[i].quan = 0;
tree[i].parent = -1;
tree[i].left = -1;
tree[i].right = -1;
tree[i].where = -1;
}
for (i = 0; i < 26; i++)//叶子节点数据导入
{
if (num[i].weight != 0)
{
tree[j].quan = num[i].weight;
tree[j].val = num[i].ch;
tree[j].time = 0;
j++;
}
}
for (i = 0; i < n - 1; i++)//建树
{
m1 = m2 = 100000;
x1 = x2 = -10;
for (j = 0; j < n + i; j++)
{
if (tree[j].quan < m1 && tree[j].parent == -1)
{
m2 = m1;
x2 = x1;
m1 = tree[j].quan;
x1 = j;
}
else if (tree[j].quan < m2 && tree[j].parent == -1)
{
m2 = tree[j].quan;
x2 = j;
}
}
tree[x1].parent = n + i;
tree[x2].parent = n + i;
tree[n + i].quan = m1 + m2;
tree[n + i].time = i;
if (m1 == m2 && tree[x1].left == -1 && tree[x1].right == -1 && tree[x2].left == -1 && tree[x2].right == -1)//两个叶子节点分左右
{
if (tree[x1].val > tree[x2].val)
{
tree[x1].where = 1;
tree[x2].where = 0;
tree[n + i].left = x2;
tree[n + i].right = x1;
}
else
{
tree[x1].where = 0;
tree[x2].where = 1;
tree[n + i].left = x1;
tree[n + i].right = x2;
}
}
else if (m1 == m2)
{
if (tree[x1].time > tree[x2].time)
{
tree[x1].where = 1;
tree[x2].where = 0;
tree[n + i].left = x2;
tree[n + i].right = x1;
}
else
{
tree[x1].where = 0;
tree[x2].where = 1;
tree[n + i].left = x1;
tree[n + i].right = x2;
}
}
else
{
tree[x1].where = 0;
tree[x2].where = 1;
tree[n + i].left = x1;
tree[n + i].right = x2;
}
// cout<<tree[n + i].quan<<"+ "<<endl;
//cout<<"zuo:"<<tree[tree[n+i].left].val<<endl;
// cout<<"you:"<<tree[tree[n+i].right].val<<endl;
}
}
void huffcode(char key,hufnode tree[])//编码
{
int pos;
hufnode temp;
int a[100] = { 0 };
int i = 0, j = 0;
for (i = 0; i < 26; i++)
{
if (tree[i].val == key || tree[i].val - key == 32 || key - tree[i].val == 32)
{
pos = i;
break;
}
}
temp = tree[pos];
while (1)
{
if (temp.parent == -1)
break;
a[j++] = temp.where;
temp = tree[temp.parent];
}
for (i = j - 1; i >= 0; i--)
cout << a[i];
}
int main()
{
char str[1001];
while (scanf("%s", str)!= EOF)
{
n=0;
hufnode tree[1000];
Weight num[26];
for (int i = 0; i < strlen(str); i++)
{
if (str[i] >= 'A' && str[i] <= 'Z')
{
num[str[i] - 65].weight++;
num[str[i] - 65].ch = str[i];
}
if (str[i] >= 'a' && str[i] <= 'z')
{
num[str[i] - 97].weight++;
num[str[i] - 97].ch = str[i];
}
}
for (int i = 0; i < 26; i++)
{
if (num[i].weight != 0)
{
n++;
if (num[i].ch >= 'A' && num[i].ch <= 'Z')//大写全部改小写
num[i].ch += 32;
}
}
creattree(num,tree);
for (int i = 0; i < strlen(str); i++)
huffcode(str[i],tree);
cout << endl;
}
return 0;
}