データ構造-10ハフマンツリー

哈夫曼树 

路径:从一个结点到另一个结点之间的分支构成这两个结点之间路径
树的路径长度:从Root到每一个结点的路径长度之和
结点数码相同的二叉树中,完全二叉树是路径长度最短的二叉树
(路径长度最短的二叉树不一定是完全二叉树)
权:给结点赋一个具有某种含义的值
结点的带权路径长度:Root到该结点之间的路径长度  * 权值
WPL树的带权路径长度:树种所有Leaf结点的带权路径长度之和   

哈夫曼树:最优树:WPL最短的树 
具有相同带权结点的哈夫曼树不唯一
//贪心算法? 

							构造森林全是根
							选用两小造新树
							删除两小添新人
							重复23剩单根 

ここに画像の説明を挿入

哈夫曼树中只有度为02的结点,没有度为1的结点
包含n个叶子结点的哈夫曼树中共有2n-1个结点 

顺序存储结构
typedef struct{
    
    
	int weight;		//权
	int parent,lch,rch; 
}HTNode,*HuffmanTree;

共有2n-1个结点,不使用0为下标,2n

void CreatHuffmanTree(HuffmanTree HT, int n){
    
    	//构造一个n个叶子哈夫曼树 
	if(n<=1)	return;s
	m= 2*n - 1;				//数组共2n-1个元素
	HT = new HTNode[m+1];	//0号单元未使用,HT[m]表示根结点
	for(i=1; i<=m;++i){
    
    
		HT[i].lch = 0;
		HT[i].rch = 0;
		HT[i].parent = 0;
	} 
	for(i = 1; i<=n; ++i)	cin>>HT[i].weight;//输入前n个元素的weight 
	
	//接下来通过n-1次合并一次产生n-1个结点HT[i],i=n+1……2n-1
	
	for(i = n+1; i <= m; i++){
    
    	//合并产生n-1个结点 
	Select(HT, i-1, s1, s2)		//在HT[k](1 <= k <= i-1) 中选择两个其双亲域为0 
	//这函数自己写				//且,weight最小的结点,返回他们在HT中的序号s1、s2 
	
	HT[s1].parent = i;	HT[s1].parent = i;	//从表中删除s1、s2 
	
	HT[i].lch = s1;	HT[i].rch = s2;			//s1、s2分别作为i的左右孩子 
	HT[i].weight = HT[s1].weight + HT[s2].weight//i的权值为s1、s2之和 
	}
} 

哈夫曼编码(看书)
任意一个编码都不是另一个字符的编码的前缀 	---前缀编码

为什么哈夫曼编码是前缀编码呢?
因为没有一个树叶是另一片的祖先 

为什么Huffman编码能够保证字符编码总长最短
因为Huffman树的带权路径长度最短 

左分支 0 右分支 1 
一看就懂,真的

ここに画像の説明を挿入

BUT,这种方法我们看好看,计算机具体算法实现较为困难

计算机从叶子往上找较为方便 

假设要得到G
从七号结点开始,取7号的parent值8,八号结点是其双亲,
查8号的左右孩子,是左孩子就0、右孩子1,
一直这样找,找到parent = 0 
最后逆序取 
有几个结点就要做多少次 

ここに画像の説明を挿入

我是没太懂
void CreatHuffmanCode(Huffman HT, HuffmanCode & HC, int n){
    
    
从叶子到root逆向求每个字符的哈夫曼编码,存储在编码表HC中
	HC = new char*[n+1];	//分配n个字符编码的头指针矢量
	cd = new char[n];		//分配临时存放编码的动态数组空间
	cd[n-1] = '\0';			//编码结束符
	
	for(i = 1; i <= n; ++i){
    
    //逐个字符求哈夫曼编码 
	start = n-1; c = i; f = HT[i].parent;
	
	while(f != 0){
    
    			//从叶子结点开始向上回溯,知道root 
	--start;				//回溯一次start向前指一个位置 
	
	if(HT[f].lchild = c)	cd[start] = '0';
	else					cd[start] = '1'; 
	c = f;f = HT[f].parent;	//继续回溯
			} 
	HC[i] = new char[n-start];	//为第i个字符串编码分配空间 
	strcpy(HC[i], &cd[start]);	//将求得的编码从临时空间cd复制到HC的当前行中 
		}
		
	delete cd;		//释放临时空间 
	}

おすすめ

転載: blog.csdn.net/fly_ship/article/details/110141084