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

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

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

由定义哈夫曼树是二叉树,那分析,构建哈夫曼树和普通的二叉树有什么区别,首先哈夫曼树的大小是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

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


相关文章
|
7月前
|
存储 C++
使用C++代码实现哈夫曼树的构造
使用C++代码实现哈夫曼树的构造
|
6月前
|
机器学习/深度学习 存储
数据结构学习记录——哈夫曼树(什么是哈夫曼树、哈夫曼树的定义、哈夫曼树的构造、哈夫曼树的特点、哈夫曼编码)
数据结构学习记录——哈夫曼树(什么是哈夫曼树、哈夫曼树的定义、哈夫曼树的构造、哈夫曼树的特点、哈夫曼编码)
170 1
|
7月前
|
C++
图解哈夫曼树
图解哈夫曼树
|
自然语言处理 算法 搜索推荐
哈夫曼树与哈夫曼编码
本文主要介绍实现哈夫曼树和哈夫曼编码
214 1
哈夫曼树与哈夫曼编码
|
存储 算法 搜索推荐
哈夫曼树、哈夫曼编码和字典树
哈夫曼树、哈夫曼编码和字典树
150 0
|
存储 数据安全/隐私保护 C++
【C++】哈夫曼树模拟实现
在解释什么是哈夫曼树之前,先介绍三个基本术语:节点的路径长度、节点的权重和树的带权路径长度。
|
机器学习/深度学习 存储 算法
408数据结构学习笔记——树与二叉树的应用——哈夫曼树和哈夫曼编码、并查集
408数据结构学习笔记——树与二叉树的应用——哈夫曼树和哈夫曼编码、并查集
249 1
408数据结构学习笔记——树与二叉树的应用——哈夫曼树和哈夫曼编码、并查集
哈夫曼树与哈夫曼编码(优先队列)
哈夫曼树与哈夫曼编码(优先队列)
387 0
哈夫曼树与哈夫曼编码(优先队列)
数据结构题:根据所给权值设计相应的哈夫曼树,并设计哈夫曼编码
数据结构题:根据所给权值设计相应的哈夫曼树,并设计哈夫曼编码
数据结构题:根据所给权值设计相应的哈夫曼树,并设计哈夫曼编码
|
存储 算法
哈夫曼树、哈夫曼编码详解
哈夫曼树、哈夫曼编码很多人可能听过,但是可能并没有认真学习了解,今天这篇就比较详细的讲一下哈夫曼树。
264 0
哈夫曼树、哈夫曼编码详解