哈夫曼树和哈夫曼编码的简单实现

简介: 哈夫曼树和哈夫曼编码的简单实现

学过数据结构自然清楚哈夫曼树是每次选择两个最小权值的结点构树,一般来说如果只是要求最小帯权路径长度,不一定要构造哈夫曼树,直接用一个优先队列就可以模拟这个过程,但是如果需要实现哈夫曼编码,这时就必须得构建哈夫曼树了。

由定义哈夫曼树是二叉树,那分析,构建哈夫曼树和普通的二叉树有什么区别,首先哈夫曼树的大小是2*n-1,大小是定的,那用静态二叉树来描述更方便,可以前n个数都是叶子节点;其次由于哈夫曼树叶子结点很明确,那构建哈夫曼编码的时候可以自结点向根,那最好定义一个父亲结点,方便自下向上寻根。

综上哈夫曼树定义如下:

struct node{   //哈夫曼树的结构,采用静态二叉树 
  int weight;
  int parent;
  int lchild,rchild; 
} Node[N]; //定义一个足够大的静态哈夫曼树


了解结构后,现在考虑,怎样定义优先队列,优先队列是定义成node型,还是其他?实际上,我们每次从优先队列拿出两个结点后,需要修改结点,又考虑到优先队列存储的只是保存数据的副本,为了便于修改,可以将其定义成int型,存放哈夫曼树的下标,注意优先队列默认是从大到小排列,这里需要修改。

综上,简单的实现哈夫曼树、哈夫曼编码如下:

#include<iostream> 
#include<queue>
#include<string>
using namespace std;
#define N 1000
struct node{   //哈夫曼树的结构,采用静态二叉树 
  int weight;
  int parent;
  int lchild,rchild; 
} Node[N]; //定义一个足够大的静态哈夫曼树 
struct cmp{   //将优先队列按从小到大排列的比较函数 
  bool operator ()(int a,int b){
  return Node[a].weight>Node[b].weight; 
  }
};
priority_queue<int,vector<int>,cmp>q;//弄成int型方便修改Node里的值 
string s[100];
void createhuff(int n){  //创建哈夫曼树 
  for(int i=1;i<=n;i++)
q.push(i);
int i,j,m=n+1;
while(q.size()>1){
  i=q.top();q.pop();
  j=q.top();q.pop();
  Node[m].weight=Node[i].weight+Node[j].weight;
  Node[m].lchild=i;Node[m].rchild=j;
  Node[i].parent=Node[j].parent=m;
  q.push(m++);
} 
}
void preorder(int root){  //前序遍历 
  if(root==0)
  return;
  printf("%d ",Node[root].weight);
  preorder(Node[root].lchild);
  preorder(Node[root].rchild);
}
void encodehuff (int n) {//生成编码,从下往上 
  for(int i=1;i<=n;i++){
  int p=Node[i].parent,k=i;
  string str;
  while(p){
    if(Node[p].lchild==k){ //这里生成的是逆向代码 
    str+="1";}
    else {
    str+="0";}  
    k=p;
    p=Node[k].parent;
  }
  for(int f=str.length();f>0;f--) //将其编码正向 
  s[i]+=str[f-1];
  }
}
void  printfcode(int n) {
  for(int i=1;i<=n;i++) 
  printf("%s\n",s[i].c_str());
  //这里用printf输出字符串需要将它转化为字符数组,用cout不用 
}
int main(){
  int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){  //从1开始,0值与空对应 
  scanf("%d",&Node[i].weight);
  Node[i].parent=Node[i].lchild=Node[i].rchild=0;
}
createhuff(n);
encodehuff(n);
printfcode(n);
return 0;
}

1685016705000.jpg

上面只是简单实现,具体应用可以添加一些输入输出,改变参数形式等。


相关文章
|
Rust Apache 对象存储
Apache Paimon V0.9最新进展
Apache Paimon V0.9 版本即将发布,此版本带来了多项新特性并解决了关键挑战。Paimon自2022年从Flink社区诞生以来迅速成长,已成为Apache顶级项目,并广泛应用于阿里集团内外的多家企业。
18091 13
Apache Paimon V0.9最新进展
|
9月前
|
运维 监控 Cloud Native
深度用云——释放企业潜能| 阿里云原生网络AIOps,助力企业深度用好云
深度用云——释放企业潜能| 阿里云原生网络AIOps,助力企业深度用好云
228 0
|
7月前
|
人工智能 小程序 计算机视觉
AI不只有大模型,小模型也蕴含着大生产力
近年来,AI大模型蓬勃发展,从ChatGPT掀起全球热潮,到国内“百模大战”爆发,再到DeepSeek打破算力壁垒,AI技术不断刷新认知。然而,在大模型备受关注的同时,许多小而精的细分模型却被忽视。这些轻量级模型无需依赖强大算力,可运行于手机、手持设备等边缘终端,广泛应用于物体识别、条码扫描、人体骨骼检测等领域。例如,通过人体识别模型衍生出的运动与姿态识别能力,已在AI体育、康复训练、线上赛事等场景中展现出巨大潜力,大幅提升了相关领域的效率与应用范围。本文将带您深入了解这些高效的小模型及其实际价值。
|
10月前
|
计算机视觉
YOLOv11改进策略【Neck】| GFPN 超越BiFPN 通过跳层连接和跨尺度连接改进v11颈部网络
YOLOv11改进策略【Neck】| GFPN 超越BiFPN 通过跳层连接和跨尺度连接改进v11颈部网络
2171 10
YOLOv11改进策略【Neck】| GFPN 超越BiFPN 通过跳层连接和跨尺度连接改进v11颈部网络
|
机器学习/深度学习 计算机视觉
YOLOv8改进 | 2023注意力篇 | EMAttention注意力机制(附多个可添加位置)
YOLOv8改进 | 2023注意力篇 | EMAttention注意力机制(附多个可添加位置)
1378 0
|
JavaScript 前端开发 Linux
【好玩的开源项目】Linux系统之部署捕鱼达人经典小游戏
【7月更文挑战第20天】Linux系统之部署捕鱼达人经典小游戏
565 8
|
并行计算 PyTorch 算法框架/工具
yolov5训练太慢的解决方案
这篇文章讨论了YOLOv5训练速度慢的问题,并提供了解决方案,主要是由于没有安装CUDA和支持GPU的PyTorch版本,导致只有CPU在工作。文章建议安装CUDA和正确配置支持GPU的PyTorch以加速训练过程。
1166 1
yolov5训练太慢的解决方案
|
弹性计算 Java 数据挖掘
基于云效流水线Flow | 高效构建企业门户网站
【6月更文挑战第18天】基于云效流水线Flow | 高效构建企业门户网站
|
前端开发 JavaScript UED
element-ui 表格数据究竟隐藏着怎样的神秘样式与格式化技巧?快来揭开谜底!
【8月更文挑战第22天】《element-ui 表格数据样式及格式化案例》展示了如何利用 element-ui 的表格组件实现美观且易读的数据展示。通过简单配置,可以自定义表格样式,如边框、背景色等,并通过 formatter 实现数据格式化,例如将成绩保留一位小数。此外,还能依据条件设置行样式,如成绩达优则高亮显示,从而增强用户体验和数据可读性。
301 1
「Mac畅玩鸿蒙与硬件15」鸿蒙UI组件篇5 - Slider和Progress组件
Slider 和 Progress 是鸿蒙系统中的常用 UI 组件。Slider 控制数值输入,如音量调节;Progress 显示任务的完成状态,如下载进度。本文通过代码示例展示如何使用这些组件,并涵盖 进度条类型介绍、节流优化、状态同步 和 定时器动态更新。
357 7
「Mac畅玩鸿蒙与硬件15」鸿蒙UI组件篇5 - Slider和Progress组件