数据结构之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树有很多应用,压缩与解压缩就与它有关。

 。

 

posted @   飞翔的猪十三  阅读(726)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示