一、问题描述
【问题描述】使用贪心算法求解Huffman编码问题,具体来说就是,根据每个字符的出现频率,
使用最小堆构造最小优先队列,构造出字符的最优二进制表示,即前缀码。在程序开始说明部分,
简要描述使用贪心算法求解Huffman编码问题的算法过程。
【输入形式】在屏幕上输入字符个数和每个字符的频率。
【输出形式】每个字符的Huffman编码。
【样例输入】
6
45 13 12 16 9 5
【样例输出】
a 0
b 101
c 100
d 111
e 1101
f 1100
【样例说明】
输入:字符个数为6,a至f每个字符的频率分别为:45, 13, 12, 16, 9, 5。
输出:每个字符对应的Huffman编码。
二、算法思路分析
哈夫曼算法以自底向上的方式构造表示最优前缀码的二叉树T。算法以|C|个叶结点开始,执行|C|-1次合并,运算后产生最终所要求的树T。在哈夫曼树中,编码字符集中每个字符c的频率是f©。以f为键值的优先队列Q在用做贪心选择时有效地确定当前要合并的两棵具有最小频率的树。一旦两棵具有最小频率的树合并后,产生一棵新的树,其频率和为合并的两棵树的频率之和,并将新树加入Q。
三、图例说明哈夫曼树
四、上代码!
#include
#define N 50 //叶子结点数
using namespace std;
char alphabet[26] = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
typedef struct {
char data;
int weight;
int parent;
int lchild;
int rchild;
}HTNode; //结点定义
typedef struct {
char cd[N]; //存放赫夫曼编码
int start; //开始指针 记录每个字母编码在cd数组里开始的位置
}HCode; //赫夫曼编码
void CreateHT(HTNode ht[],int n) //构造n个叶子结点的赫夫曼树
{
int i,k,lnode,rnode;
int min1,min2; //存放最小的两个结点
for(i = 0; i < 2*n-1; i++) //将所有结点的双亲指针置为NULL
{
ht[i].parent = -1;
ht[i].lchild = -1;
ht[i].rchild = -1;
}
for(i = n; i < 2*n-1; i++)
{
min1 = min2 = 32767; //每次循环时都将min初始化
lnode = -1; //lnode存最小的,rnode存次小的
rnode = -1;
for(k = 0; k <= i-1; k++) //遍历现在存在的i个结点
{
if(ht[k].parent == -1) //没有父母结点的才判断
{
if(ht[k].weight < min1)
{
min2 = min1;
rnode = lnode; //有比min1还小的,原min1就变成了次小的,赋给min2
min1 = ht[k].weight;
lnode = k;
}
else if(ht[k].weight < min2)
{
min2 = ht[k].weight;
rnode = k;
}
}
}
ht[lnode].parent = i;
ht[rnode].parent = i;
ht[i].weight = ht[lnode].weight + ht[rnode].weight;
ht[i].lchild = lnode;
ht[i].rchild = rnode;
}
}
void CreateHCode(HTNode ht[],HCode hcd[],int n) //构造赫夫曼编码
{
int i,f,c;
HCode hc;
for(i = 0; i < n; i++)
{
hc.start = n;
c = i;
f = ht[i].parent;
while (f!= -1)
{
if(ht[f].lchild == c)
hc.cd[hc.start--] = '0';
else
hc.cd[hc.start--] = '1';
c = f;
f = ht[f].parent;
}
hc.start++;
hcd[i] = hc;
}
}
void Output(HTNode ht[],HCode hcd[],int n) //输出赫夫曼编码
{
int i,j;
for(i = 0; i < n; i++)
{
cout<<ht[i].data<<" ";
for(j = hcd[i].start; j <= n; j++)
cout<<hcd[i].cd[j];
cout<<endl;
}
}
int main()
{
int n;
cin>>n;
HTNode ht[2*n-1]; //赫夫曼树=>赫夫曼树中总结点数 = 2*叶子结点-1
HCode hcd[n]; //n个结点的赫夫曼编码
for(int i = 0; i < n; i++)
{
ht[i].data = alphabet[i];
}
for(int i = 0; i < n; i++)
{
cin>>ht[i].weight;
}
CreateHT(ht, n);
CreateHCode(ht, hcd, n);
Output(ht, hcd, n);
}
帮助到你请点赞➕收藏➕关注哦~