哈夫曼树 与 哈夫曼编码 (由最小堆构建)复习

36 篇文章 0 订阅
18 篇文章 0 订阅

哈夫曼树

每个结点的权值乘以与根结点的路径长度之和最小的树——最优二叉树
哈夫曼树的特点:
 没有度为1的结点;
 哈夫曼树的任意非叶节点的左右子树交换后仍是哈夫曼树;  n个叶子结点的哈夫曼树共有2n-1个结点;
 对同一组权值{w1 ,w2, …… , wn},存在不同构的哈夫曼树
哈夫曼树的构成
将二叉树按结点权值大小转化成最小堆,每次取堆定两个元素组成新的二叉树结点,插回堆中;
当进行size-1次合并,最后所得的即为哈夫曼树;

1.树结点

#include <iostream>
#include <string>
using namespace std;
#define MaxNum 64

struct TreeNode{
    int Weight = 0;
    TreeNode *Left = nullptr;
    TreeNode *Right = nullptr;
};

2.堆结构

struct HeapNode{// 堆结构
	TreeNode Data[MaxNum];      //data内放着树结构
	int Size =0;        //初始大小为0 
};

3.堆创建函数

HeapNode * CreateHeap(){    //建树——返回指向树根节点的指针 
	HeapNode *H = new(HeapNode);
	H->Data[0].Weight = -1;    //哨兵的weight设置为-1
	return H;       //建堆——一次即可 
}

4.堆删除函数

TreeNode *DeleteMin(HeapNode *H){ //返回堆定的指针 
	int Parent = 0 , Child=0;
	TreeNode temp;
	TreeNode *MinItem = new(TreeNode);       //新建一个minitem
	*MinItem = H->Data[1];   //保存堆顶
	
	temp = H->Data[(H->Size)--];   //拿到堆底的对象,并且size-1
	
	for(Parent=1;Parent *2 <= H->Size; Parent=Child)
	{
		Child= Parent*2;
		//Size就是为了作为边界 
		if(Child!=H->Size && (H->Data[Child].Weight>H->Data[Child+1].Weight))
			Child++;
		if(temp.Weight<=H->Data[Child].Weight)  break;
		else H->Data[Parent]=H->Data[Child];        //下沉 
	}
	//break出来说明找到合适位置 
	 H->Data[Parent] = temp;     //进行赋值
	 return MinItem;       //返回堆定成员指针 
} 

5.插入堆操作

void Insert(HeapNode *H, TreeNode *item){     //将一个树成员插入堆中 
	int i=0;
	i= ++(H->Size);    //i为当前总容量
	//item为指向树成员的指针 
	for (;item ->Weight<H->Data[i/2].Weight;i/=2)  //插入最后,然后上浮 
	//当要插入的成员小于父节点,上浮 
	{
		H->Data[i]=H->Data[i/2];
	 } 
	 H->Data[i] = *item;       //将item所指成员放入堆中 
} 

6.构建哈夫曼树
输入一个最小堆对象的指针;

TreeNode *Huffman(HeapNode *H){    //把堆变为哈夫曼树 
	TreeNode *T = nullptr;     //初始空指针
	 int num = H->Size;      //一共有num个元素
	 //进行n-1次合并
	 for(int i=0;i<num-1;i++)
	 {
	 	T= new(TreeNode);
	 	T->Left = DeleteMin(H);
	 	T->Right = DeleteMin(H);
	 	T->Weight=T->Left->Weight + T->Right->Weight;
	 	Insert(H,T);    //T为指针——insert(H,T)
		 //要用动态内存创造空间时——用指针 
	  } 
	  T= DeleteMin(H);    
	  return T;      //返回指向堆头的指针 
	  // 
}

总结
哈夫曼树由最小堆转化而来;
可以使得二叉树为最优二叉树;
可以避免二义性,构造编码代价最少的二叉树;

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值