数据结构之Huffman树的C++实现
一、HUffman树百度百科的定义如下:
给定N个权值作为N个叶子结点,构造一棵二叉树,若该树的带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree)。哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近。
二、Huffman树的构造方法:
1、在N个节点组成的节点集合中选取两个权值最小的节点组成一棵树,新树的根节点的权值为两个节点权值之和。
2、在节点集合中删除这两个节点。
3、将根节点加入节点集合
4、重复以上过程直到节点集合中只剩一个节点
节点集合{1,2,3,4,5}
在节点集合中删除最小的两个节点,加入新的节点
构造完成后的Huffman树
三、Huffman树的C++实现
由上面的过程看一个Huffman树上的节点定义可以如下:
权值(weight)、父节点位置(parent)、左右儿子节点位置(lchild、rchild)
1 #include<iostream> 2 #include<queue> 3 #include<vector> 4 using namespace std; 5 struct Huffman { 6 int weight;//权值 7 int lchild, rchild;//左、右孩子 8 int parent;//父节点 9 10 //这个构造函数是因为最开始每个节点都是单独的树,儿子节点父节点均不存在 11 //方便初始化 12 Huffman(int w){ 13 weight = w; 14 lchild = -1; 15 rchild = -1; 16 parent = -1; 17 } 18 Huffman(int w,int l,int r,int p) { 19 weight = w; 20 lchild = l; 21 rchild = r; 22 parent = p; 23 } 24 25 };
我们可以用vector定义一个节点集合,叫做Huffman表
1 vector<Huffman> arg;//Huffman表 2 //构造Huffman树并返回Huffman树头位置 3 int Huffman_head() { 4 int n = (int)arg.size();//元素计数器 5 while (n!=1) { 6 int min_1 = -1; 7 int min_2 = -1; 8 //在节点集合中找到最小的元素 9 for (int min_k = 0; min_k < (int)arg.size(); min_k++) { 10 if (arg.at(min_k).parent != -1) 11 continue; 12 if (min_1 == -1) 13 min_1 = min_k; 14 if (arg.at(min_k).weight < arg.at(min_1).weight) 15 min_1 = min_k; 16 } 17 arg.at(min_1).parent = (int)arg.size(); 18 //在节点集合中找到第二小的元素 19 for (int min_k = 0; min_k < (int)arg.size(); min_k++) { 20 if (arg.at(min_k).parent != -1) 21 continue; 22 if (min_2 == -1) 23 min_2 = min_k; 24 if (arg.at(min_k).weight < arg.at(min_2).weight) 25 min_2 = min_k; 26 } 27 arg.at(min_2).parent = (int)arg.size() ; 28 Huffman x (arg.at(min_1).weight + arg.at(min_2).weight, min_1, min_2, -1); 29 arg.push_back(x);//加入新节点 30 n--; 31 32 } 33 34 return (int)arg.size() - 1;//最后的节点一定是最末尾的值 35 36 }
利用队列打印Huffman表
1 void print(int head) { 2 queue<int> pr; 3 cout<<"Num\t" << "weight\t" << "lchlid\t" << "rchild\t" << "parent\t" << endl; 4 pr.push(head); 5 while (!pr.empty()) { 6 int x = pr.front(); 7 if(arg.at(x).lchild != -1) 8 pr.push(arg.at(x).lchild); 9 if(arg.at(x).rchild != -1) 10 pr.push(arg.at(x).rchild); 11 cout << x << "\t" << arg.at(x).weight << "\t" << arg.at(x).lchild << "\t" << arg.at(x).rchild << "\t" << arg.at(x).parent << "\t" << endl; 12 pr.pop(); 13 } 14 15 16 }
测试代码
int main() { arg = { {1},{2},{3},{4},{5} }; int p = Huffman_head(); print(p); return 0; }
结果如下
这只是Huffman树最简单的构造方法之一,Huffman树有很多应用,压缩与解压缩就与它有关。
。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现