哈夫曼树

哈夫曼树的构造

如何构造最优叶子二叉树?Huffman给出了一个简单而又漂亮的算法,这个算法称为哈夫曼算法。它的基本思想是要让权大的叶子离根最近。具体作法是:

(1)根据给定的n个权值{},构造n棵二叉树的集合={},其中每棵二叉树中均只含一个带权值为的根结点,其左、右子树为空树;

(2)在F中选取其根结点的权值为最小的两棵二叉树,分别作为左、右子树构造一棵新的二叉树,并置这棵新的二叉树根结点的权值为其左、右子树根结点的权值之和;

(3)从F中删去这两棵树,同时加入刚生成的新树;

(4)重复(2)和(3)两步,直到F中只含一棵树为止。

从上述算法中可以看出,F实际上是森林,该算法的思想是不断地进行森林F中的二叉树的"合并",最终得到哈夫曼树。

实际上,哈夫曼算法的实现与实际问题所采用的存储结构有关。现假设用数组F来存储哈夫曼树,其中第i个数组元素Fi是哈夫曼树中的一个结点,其地址为i,有3个域,Data域存放该结点的权值,lChild域和rChild域分别存放该结点左、右子树的根结点的地址(下标)。在初始状态下: Fi.Data=Wi,Fi.lChild=Fi. rChild=0,i=1,2,...,n。

即先构造了n个方形叶子。在以后每步构造一棵新二叉树时,都需要对森林中所有二叉树的根结点进行排序,因此可用数组a作为排序暂存空间,其中第i个数组元素ai是森林F中第i棵二叉树的根结点,有2个域,Data是根结点所对应的权值,Addr是根结点在F中的地址(下标)。在初始状态下:

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=1005;
struct link{
	int lchild,rchild,data,addr;
}a[maxn],f[maxn]; //a[]暂储存根节点信息,f[]储存所有节点 
int n;
void sor(int k){ //对a[]前 k个元素按 data 升序排列。
	for(int i=1;i<k;i++){
		for(int j=i+1;j<=k;j++){
			if(a[i].data>a[j].data) swap(a[i],a[j]);
		}
	}
	return ;
}
void vist(int t){ //前序遍历打印节点权值 
	if(f[t].data==0) return ;
	cout<<f[t].data<<" ";
	vist(f[t].lchild);
	vist(f[t].rchild);
	return ;
}
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i].data;
		f[i].data=a[i].data; //同步至 f[]作为叶子节点
		a[i].addr=i;  //记录自身在 f[]中的位置
	}
	//[建树阶段]
	int t,i;
	t=n+1,i=n; //t 新节点起始位置,i 当前森林中的树数量
	while(i>1){
		sor(i); //确保 a[1],a[2]最小
		//合并最小的两个根节点
		f[t].data=a[1].data+a[2].data; //新节点权值 = 两个最小权值之和
		f[t].lchild=a[1].addr; //左孩子指向第一个最小节点
		f[t].rchild=a[2].addr; //右孩子指向第二个最小节点
		//更新森林状态
		a[1].data=f[t].data; //将新节点权值存入 a[1]
		a[1].addr=t; //更新 a[1] 指向新节点在 f[]中的地址
		a[2].addr=a[i].addr; //用末尾元素覆盖 a[2](删除已合并节点)
		t++; //准备下一个新节点的存储位置
		i--; //森林中树的数量减1
	}
	vist(t-1); //从前序遍历整棵树(根节点在t-1处) 
	return 0;
}
相关推荐
旖旎夜光1 分钟前
LeetCode 904:水果成篮(滑动窗口) —— 题解
数据结构·c++·算法·leetcode·滑动窗口
乐观勇敢坚强的老彭2 小时前
C++ 竞赛常用算法模板速查表
开发语言·c++·算法
我变成萤火虫2 小时前
河南萌新联赛2026第(三)场:郑州轻工业大学
数据结构·c++·算法·贪心算法·stl·深度优先·哈希算法
白狐_7982 小时前
408数据结构第7章:B树①——基础概念与结构
数据结构·b树
buhuizhiyuci2 小时前
【Linux 篇】数字世界的水流蓄水池 —— IO 缓冲区机制深度实战解析
linux·运维·服务器·c++
liulilittle3 小时前
LLM 推理引擎与内核系统工程原理
c++·ai·llm·内存·memory·core·kernel
Suxing93 小时前
C语言基础分享:从“租房”到“拆迁”,C语言动态内存管理
java·数据结构·算法
啦啦啦啦啦zzzz3 小时前
moduo网络库 Acceptor TcpConnection
服务器·网络·c++·reactor·网络库
键盘会跳舞3 小时前
C++:右值引用与移动语义源码级深度拆解——现代C++性能优化的语言基石
c++·右值引用·移动语义
码匠许师傅3 小时前
【C++ 面试真题】聊聊 C++ 的虚函数和多态
java·c++·面试