PTA 05-树9 Huffman Codes

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 
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值