今天看了趣学算法中的有关哈夫曼树的一个问题,就蛮有兴致再写一次哈夫曼树,但这个算法的实现和我之前的哈夫曼的实现方法略有不同。 声明一下,这个实现我是采纳书上的,觉得还不错,就写了。
回顾
这个问题是这样描述的:
在远距离的信息通信过程和大容量数据存储方面运用比较广泛的数据压缩就是采用哈夫曼编码进行的。如果让我们尝试一次,哈夫曼树应该如何实现呢?
回忆一下:哈夫曼树的几个性质,我们要知道,哈夫曼树没有度为一的结点,而且N个叶子结点的哈夫曼树具有 2 * N - 1个结点 。然后呢,利用类似二叉树的分为左右两个孩子节点起关系连接作用。最后呢,我们所求得到的编码要是从叶子节点到根节点路径。了解这一些,我们就开始吧。
实现过程
我们采用的struct的存储方式,其中struct的结构体内容有
int lchild;//左孩子
int rchild;//右孩子
double weight;//权值
char value;//该节点所代表的字符
然后呢,与之前的不一样的地方来了,我们将每个叶子节点到
根节点的路径都分别用数组存起来,而不是直接建立二叉树然后遍历求权重,就如同
直接利用数字 0 和 1来区分该节点的左右孩子;
首先固定数组的最大长度,例如:bit[Maxsize],将 Maxsize 赋值为至少为 2 * N - 1;
然后呢就会这样:0 1 0 1 1 0 1表示哈夫曼编码;我觉得这样实现,比我以前的实现方法好一点,
文末附上我之前的实现方法的链接。
现在就是代码实现c++(这是原书上的)
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdlib>
using namespace std;
#define Maxbit 100
#define Maxvalue 1000000
#define Maxleaf 30
#define Maxnode Maxleaf * 2 - 1
typedef struct{ //节点结构体
double weight;
int parent;
int lchild;
int rchild;
char value;
}HnodeType;
HnodeType HuffNode[Maxnode]; //节点结构体
typedef struct{
int bit[Maxbit];//结点的编码
int start;//开始下标
}HcodeType;
HcodeType Huffcode[Maxleaf];//编码结构体数组
void HuffmanTree(HnodeType HuffNode[Maxnode],int n)
{
int i,j,x1,x2;
double m1,m2;
for(i = 0;i < 2* n - 1;i++)
{
HuffNode[i].weight = 0;
HuffNode[i].lchild = -1;
HuffNode[i].rchild = -1;
HuffNode[i].parent = -1;
}
for(i = 0;i <= n - 1;i++)
{
cout<<"Please input value and weight of leaf node "<<i + 1<<endl;
cin>>HuffNode[i].value>>HuffNode[i].weight;
}
for(i = 0; i < n - 1;i++)
{
m1 = m2 = Maxvalue;//无父节点且权值最小的两个节点
x1 = x2 = -1;
for(j = 0;j < n + i;j++)
{
if(HuffNode[j].weight < m1 && HuffNode[j].parent == -1)
{
m2 = m1;//权值
x2 = x1;//编号
m1 = HuffNode[j].weight;
x1 = j;
}
else if(HuffNode[j].weight < m2 && HuffNode[j].parent == -1)
{
m2 = HuffNode[j].weight;
x2 = j;
}
}
HuffNode[x1].parent = n + i;
HuffNode[x2].parent = n + i;
HuffNode[n+i].weight = m1 + m2;
HuffNode[n+i].lchild = x1;
HuffNode[n+i].rchild = x2;
}
return ;
}
void HuffmanCode(HcodeType Huffcode[Maxleaf],int n)
{
HcodeType cd;
int i,j,c,p;
for(i = 0;i <= n - 1;i++)
{
cd.start = n - 1;
c = i;
p = HuffNode[c].parent;
while(p != -1)
{
if(HuffNode[p].lchild == c)
cd.bit[cd.start] = 0;//左孩子
else
cd.bit[cd.start] = 1;//右孩子
cd.start--;//向前移动一位
c = p;
p = HuffNode[c].parent;
}
for(j = cd.start + 1;j <= n - 1;j++)
Huffcode[i].bit[j] = cd.bit[j];
Huffcode[i].start = cd.start;
}
return ;
}
int main()
{
int n,i,j;
cout<<"请输入节点个数 :";
cin>>n;
HuffmanTree(HuffNode,n);
HuffmanCode(Huffcode,n);
for(i = 0;i <= n - 1;i++)
{
cout<<HuffNode[i].value<<": Hffuman code is : ";
for(j = Huffcode[i].start + 1;j < n ;j ++)
cout<<Huffcode[i].bit[j];
cout<<endl;
}
return 0;
}
这个是稍微改动的c语言实现,没有测试
#include<stdio.h>
#define Maxsize 1000
typedef struct{ //节点结构体
double weight;
int parent;
int lchild;
int rchild;
char value;
}Hnode;
Hnode HuffNode[Maxsize]; //节点结构体
typedef struct{
int bit[Maxsize];//结点的编码
int start;//开始下标
}Hcode;
Hcode Huffcode[Maxsize];//编码结构体数组
void HuffmanTree(int n)
{
int i,j,x1,x2;
double m1,m2;
for(i = 0;i < 2 * n - 1;i++) //初始化
{
HuffNode[i].weight = 0;
HuffNode[i].lchild = -1;
HuffNode[i].rchild = -1;
HuffNode[i].parent = -1;
}
for(i = 0;i <= n - 1;i++)
{
printf("Please input value and weight of leaf node %d\n",i + 1);
scanf("%c %lf\n",&HuffNode[i].value,&HuffNode[i].weight);
}
for(i = 0;i < n - 1;i++)
{
m1 = Maxsize;
m2 = Maxsize;
x1 = -1;
x2 = -1;
for(j = 0;j < n + i;j++)
{
if(HuffNode[j].weight < m1 && HuffNode[j].parent == -1)
{
m2 = m1;
x2 = x1;
m1 = HuffNode[j].weight;//最小值
x1 = j;
}
else if(HuffNode[j].weight < m2 && HuffNode[j].parent == -1)
{
m2 = HuffNode[j].weight; //次小值
x2 = j;
}
}
HuffNode[x1].parent = n + i;//合并两个节点
HuffNode[x2].parent = n + i;
HuffNode[n+i].weight = m1 + m2;
HuffNode[n+i].lchild = x1;
HuffNode[n+i].rchild = x2;
}
return ;
}
void HuffmanCode(int n)
{
int i,j,k;
Hcode temp;
for(i = 0;i <= n - 1;i++)
{
temp.start = n - 1;
j = i;
k = HuffNode[j].parent;
while(k != -1)
{
if(HuffNode[k].lchild == j)
temp.bit[temp.start] = 0;
else
temp.bit[temp.start] = 1;
temp.start--;
j = k;
k = HuffNode[j].parent;
}
for(j = temp.start + 1;j <= n - 1;j++)
{
Huffcode[i].bit[j] = temp.bit[j];//传给编码结构体
}
Huffcode[i].start = temp.start;//开始位置
}
return ;
}
int main()
{
int n,i,j;
printf("请输入节点个数 :");
scanf("%d",&n);
HuffmanTree(n);//树的编码
HuffmanCode(n);//计算存储路径
for(i = 0;i <= n - 1;i++)
{
printf("%c : Hffuman code is :",HuffNode[i].value);
for(j = Huffcode[i].start + 1;j < n ;j ++) //输出路径
printf("%d",Huffcode[i].bit[j]);
printf("\n");
}
return 0;
}
来源:https://blog.csdn.net/qq_44116998/article/details/100833404