代码参考:https://blog.csdn.net/u011386173/article/details/95651745
题目:05-树9 Huffman Codes (30分)
算法分析
最优编码要求:
- WPL值最小
- 无歧义解码
问题总结
-
最小堆使用数组存储,Huffman Tree结点使用链表存储怎样将二者建立联系?
-
答:最小堆中的数组可以存储Huffman Tree结点的地址,也就是建立指针数组
代码
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<string.h>
typedef struct{
char Character;
int Frequency;
}Node;
typedef struct TreeNode *HuffmanTree;
typedef HuffmanTree ElementType;
typedef struct HNode *MinHeap;
struct HNode {
ElementType *Data;
int Size;
int Capacity;
};
struct TreeNode{
int Weight;
HuffmanTree Left,Right;
};
MinHeap CreateHeap( int MaxSize );
HuffmanTree CreateHuff();
bool IsFull( MinHeap H );
bool Insert( MinHeap H, ElementType X );
bool IsEmpty( MinHeap H );
ElementType DeleteMin( MinHeap H );
HuffmanTree Huffman(MinHeap H);
int WPL(HuffmanTree T,int Depth);
void ReadData(MinHeap H,Node Array[]);
int main()
{
int N;
scanf("%d",&N);
Node Array[N];
{
int i;
for(i=0;i<N;i++){
getchar();
scanf("%c %d",&Array[i].Character,&Array[i].Frequency);
}
}
/*建堆*/
MinHeap H=CreateHeap(N);
/*把频数存入堆中*/
ReadData(H,Array);
/*先把堆整理为最小堆,然后再把最小堆整理为Huffman Tree*/
HuffmanTree T=Huffman(H);
/*计算Huffman Tree的WPL*/
int CodeLen=WPL(T,0);
/*
1、计算出一个学生测试数据的实际WPL
2、根据学生的测试数据构建一颗新的普通树,建树过程中标记每行数据的叶结点,检查叶节点是否是叶结点
*/
int M;
scanf("%d",&M);
int i;
for(i=0;i<M;i++){
int sum=0;
int flag=1;
HuffmanTree Root=CreateHuff();
HuffmanTree touch;
char c;
char s[63]="\0";
int j;
for(j=0;j<N;j++){
getchar();
scanf("%c %s",&c,&s);
int sl=strlen(s);
sum+=sl*(Array[j].Frequency);
if(flag==0)continue;
touch=Root;
int k=0;
for(k=0;k<sl;k++){
if(s[k]=='0'){
if(touch->Left==NULL){
touch->Left=CreateHuff();
}else{
if(touch->Left->Weight==1){
flag=0;
break;
}
}
touch=touch->Left;
}else if(s[k]=='1'){
if(touch->Right==NULL){
touch->Right=CreateHuff();
}else{
if(touch->Right->Weight==1){
flag=0;
break;
}
}
touch=touch->Right;
}
if(k==sl-1){
touch->Weight=1;
if(touch->Left||touch->Right){
flag=0;
}
}
}
}
if(flag==1&&sum==CodeLen){
printf("Yes\n");
}else{
printf("No\n");
}
}
return 0;
}
MinHeap CreateHeap( int MaxSize )
{
MinHeap H = (MinHeap)malloc(sizeof(struct HNode));
H->Data = (ElementType *)malloc((MaxSize+1)*sizeof(ElementType));
H->Size = 0;
H->Capacity = MaxSize;
H->Data[0] = CreateHuff();
return H;
}
HuffmanTree CreateHuff()
{
HuffmanTree T=(HuffmanTree)malloc(sizeof(struct TreeNode));
T->Weight=0;
T->Left=NULL;
T->Right=NULL;
return T;
}
bool IsFull( MinHeap H )
{
return (H->Size == H->Capacity);
}
bool Insert( MinHeap H, ElementType X )
{
int i;
if ( IsFull(H) ) {
printf("最小堆已满");
return false;
}
i = ++H->Size;
for ( ; H->Data[i/2]->Weight > X->Weight; i/=2 )
H->Data[i] = H->Data[i/2];
H->Data[i] = X;
return true;
}
bool IsEmpty( MinHeap H )
{
return (H->Size == 0);
}
ElementType DeleteMin( MinHeap H )
{
int Parent, Child;
ElementType MinItem, X;
if ( IsEmpty(H) ) {
printf("最小堆已为空");
return NULL;
}
MinItem = H->Data[1];
X = H->Data[H->Size--];
for( Parent=1; Parent*2<=H->Size; Parent=Child ) {
Child = Parent * 2;
if( (Child!=H->Size) && (H->Data[Child]->Weight>H->Data[Child+1]->Weight) )
Child++;
if( X->Weight <= H->Data[Child]->Weight ) break;
else H->Data[Parent] = H->Data[Child];
}
H->Data[Parent] = X;
return MinItem;
}
HuffmanTree Huffman(MinHeap H)
{
int i;
HuffmanTree T;
int times=H->Size;
for(i=1;i<times;i++){
T=(HuffmanTree)malloc(sizeof(struct TreeNode));
T->Left=DeleteMin(H);
T->Right=DeleteMin(H);
T->Weight=T->Left->Weight+T->Right->Weight;
Insert(H,T);
}
T=DeleteMin(H);
return T;
}
int WPL(HuffmanTree T,int Depth)
{
if(!T->Left&&!T->Right){
return (Depth*T->Weight);
}else{
return (WPL(T->Left,Depth+1)+WPL(T->Right,Depth+1));
}
}
void ReadData(MinHeap H,Node Array[])
{
int i;
for(i=0;i<H->Capacity;i++){
HuffmanTree t=CreateHuff();
t->Weight=Array[i].Frequency;
Insert(H,t);
}
}