PTA 05-树9 Huffman Codes
题目理解
【来自陈越姥姥的讲解视频和PPT+自己的记录】
(1)Huffman编码不唯一
0和1可能互换
树的形状可能不一样
但是都是最优Huffman编码
注意:最优编码不一定通过Huffman算法得到!
因此题意不能
仅仅理解为:编码是否符合Huffman树
(2)HuffmanCodes的特点
1.最优编码——总长度(WPL)最小
2.无歧义解码——前缀码:数据仅存于叶子结点
3.没有度为1的结点——满足1,2则必然有3(题目不必单独判断)
满足2和3的不一定满足1,因此不可以通过23直接判断是否HuffanTree(不可以跳过建树判断最优编码)
计算WPL
MinHeap H=CreateHeap(H);//建立空的、容量为N的最小堆
H=ReadData(N);//将f[]读入H->Data中
HuffmanTree T=Huffman(H);//建立Huffman树
int CodeLen=WPL(T,0);//计算WPL
递归计算WPL:
思想:该结点的WPL=左结点的WPL+右节点的WPL
int WPL(HuffmanTree T,int Depth){
if(!T->Left&&!T->Right){
//叶子节点=哈弗曼结点
return T->Weight*Depth;
}else{
return (WPL(T->Left,Depth+1)+WPL(T->Right,Depth+1));
//左右子树的WPL和,注意Depth+1
}
}
检查编码
(1)长度是否正确
Len=求和strlen(code[i])*f[i];
比较Len和WPL值
注意:Code[i]的最大长度为?
N-1
(斜树->肯定错)
(2)建树的过程中检查是否满足前缀码要求
Code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MINDATA -10001
#define ERROR NULL
//哈夫曼树结点
typedef struct TreeNode *HuffmanTree;
struct TreeNode{
int Weight;
HuffmanTree Left, Right;
};
//最小堆
typedef struct HNode *Heap;
typedef Heap MaxHeap;
typedef Heap MinHeap;
typedef TreeNode ElementType; //堆中每个结点都是哈夫曼树结点的类型
struct HNode {
ElementType *Data;
int Size;
int Capacity;
};
MinHeap CreateHeap( int MaxSize ) {
MinHeap H = (MinHeap)malloc(sizeof(struct HNode));
//因为0位置是哨兵,所以MaxSize+1
H->Data = (ElementType *)malloc((MaxSize+1) * sizeof(ElementType));
H->Size = 0;
H->Capacity = MaxSize;
H->Data[0].Weight = MINDATA;
H->Data[0].Left = H->Data[0].Right = NULL;
return H;
}
bool IsFull( MinHeap H ){
return (H->Size == H->Capacity);
}
bool Insert( MinHeap H, HuffmanTree T ) {
//将元素X插入堆,其中H->Data[0]已经定义为哨兵
int i;
if( IsFull(H) ){
printf("最小堆已满");
return false;
}
i = ++H->Size; //i指向插入后堆中最后一个元素的位置
for( ; H->Data[i / 2].Weight > T->Weight; i /= 2)
H->Data[i] = H->Data[i / 2];
H->Data[i] = *T;
return true;
}
bool IsEmpty( MinHeap H ) {
return (H->Size == 0);
}
HuffmanTree DeleteMin( MinHeap H ) {
//从最小堆H中取出键值最小的元素,并删除一个结点;
int Parent, Child;
ElementType X;
HuffmanTree MinItem = (HuffmanTree)malloc(sizeof(struct TreeNode));
if( IsEmpty(H) ){
printf("最小堆已空");
return ERROR;
}
*MinItem = H->Data[1]; //取出根节点存放最小值
//用最小堆最后的一个元素从根结点开始向上过滤下层结点
X = H->Data[H->Size--];
for( Parent = 1; 2 * Parent <= H->Size; Parent = Child){
//Child指向左右子结点的较小者
Child = 2 * Parent;
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 CreateHuffmanNode(int weight){
HuffmanTree T = (HuffmanTree)malloc(sizeof(struct TreeNode));
T->Weight