题目描述
对输入的英文大写字母进行统计概率 然后构建哈夫曼树,输出是按照概率降序排序输出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
代码
#include <iostream>
#include<algorithm>
using namespace std;
int a[128]= {0};
template<typename E, typename T>
struct HuffmanNode
{
T weight;
E elem;
int parent;
int lchild;
int rchild;
HuffmanNode(E em, T wt, int p=-1, int lc=-1, int rc=-1):weight(wt),elem(em)
{
parent=p;
lchild=lc;
rchild=rc;
}
HuffmanNode(int p=-1, int lc=-1, int rc=-1)
{
parent=p;
lchild=lc;
rchild=rc;
}
};
template<typename E, typename T>
class HuffmanCoder
{
private:
HuffmanNode<E, T> *root;
int maxSize;
string * codebook;//每个字母编码的字符串数组
void MakeEmpty(HuffmanNode<E, T>* root)
{
delete [] root;
}
public:
HuffmanCoder(E* elems, T* weights, int n) //构建哈夫曼树
{
int m=2*n-1;//m为总的节点个数
maxSize=m;
root=new HuffmanNode<E, T>[m];
codebook = new string [n];//编码不是在结构体中,而是在新的字符串数组,通过下标得到
for(int i= 0; i<n; i++)
{
codebook[i]="";
root[i].elem=elems[i];
root[i].weight=weights[i];
}
int min1,min2;
int pos1,pos2;
for(int i=n; i<m; i++)
{
min1=0x7fffffff;
min2=0x7fffffff;
for(int j=0; j<i; j++)
{
if(root[j].parent==-1)
{
if(root[j].weight<min1)
{
min2=min1;
pos2=pos1;
min1=root[j].weight;
pos1=j;
}
else if(root[j].weight<min2)
{
min2=root[j].weight;
pos2=j;
}
}
}
root[i].lchild=pos1;
root[i].rchild=pos2;
root[i].weight=root[pos1].weight+root[pos2].weight;
root[pos1].parent=i;
root[pos2].parent=i;
}
}
~HuffmanCoder()
{
MakeEmpty(root);
delete [] codebook;
}
void Encoder(int n)
{
int current;
int father;
for(int i=0; i<n; i++)
{
current=i;
while(root[current].parent!=-1)
{
father=root[current].parent;
if(root[father].lchild==current)
codebook[i]+="0";
if(root[father].rchild==current)
codebook[i]+="1";
current=father;
}
}
}
void OutputCode()
{
int i;
for(i=0; i<(maxSize+1)/2; i++)
{
reverse(codebook[i].begin(),codebook[i].end());
cout<<root[i].elem<<" "<<root[i].weight<<" "<<codebook[i]<<endl;
}
}
};
bool compare(char ch1,char ch2)
{
return a[(int)ch1]>a[(int)ch2];
}
bool compare_2(int a,int b)
{
return a>b;
}
int main()
{
int n,sum=0,k=0;//sum为字母的种类
cin>>n;
char* elems;
int * weights;
char ch;
for(int i=0; i<n; i++)
{
cin>>ch;
a[ch]++;
}
for(int i=65; i<=90; i++)
{
if(a[i]!=0)
{
sum++;
}
}
elems=new char[sum];
weights=new int[sum];
for(int i=65; i<=90; i++)
{
if(a[i]!=0)
{
elems[k]=(char)i;
weights[k]=a[i];
k++;
}
}
sort(elems,elems+sum,compare);
sort(weights,weights+sum,compare_2);//构建哈夫曼树的数组需要是排序过的,还需要与权对应
HuffmanCoder<char, int> coder(elems, weights, sum);
coder.Encoder(sum);//给字母编码
coder.OutputCode();
return 0;
}
构建哈夫曼树代码+手稿图(粗糙)
HuffmanCoder(E* elems, T* weights, int n) //构建哈夫曼树
{
int m=2*n-1;//m为总的节点个数
maxSize=m;
root=new HuffmanNode<E, T>[m];
codebook = new string [n];//编码不是在结构体中,而是在新的字符串数组,通过下标得到
for(int i= 0; i<n; i++)
{
codebook[i]="";
root[i].elem=elems[i];
root[i].weight=weights[i];
}
int min1,min2;
int pos1,pos2;
for(int i=n; i<m; i++)
{
min1=0x7fffffff;
min2=0x7fffffff;
for(int j=0; j<i; j++)
{
if(root[j].parent==-1)
{
if(root[j].weight<min1)
{
min2=min1;
pos2=pos1;
min1=root[j].weight;
pos1=j;
}
else if(root[j].weight<min2)
{
min2=root[j].weight;
pos2=j;
}
}
}
root[i].lchild=pos1;
root[i].rchild=pos2;
root[i].weight=root[pos1].weight+root[pos2].weight;
root[pos1].parent=i;
root[pos2].parent=i;
}
}