#include "stdafx.h"
#include <iostream.h>
#include <malloc.h>

int const ELEMENTCOUNT=5; //判断条件的个数,即初始根节点的数量
struct node


{
float wt; //权值
int parent,lchild,rchild; //双亲的下标,左子树下标,右子树下标
char data; //该节点的值,这是我加的,方便我在显示的时候验证是否正确
};

typedef node hftree[2*ELEMENTCOUNT-1]; //保存所有Huffman树的节点的数组,需要2N-1个元素

//count:初始根结点的数量,WT[]保存各节点的权值,tree为huffman树
//算法中我没有使用书上的变量名,说实话,书上变量名乱起(i,j,k,x,y,m,n
.),我看明白了算法后才知道各个变量的意义.
void huffman(int count,float WT[],hftree & tree)


{
float minWT1=0,minWT2=0; //保存第一小和第二小权值
int minE1=0,minE2=0; //保存第一小和第二小的根的在数组中的下标
int i=0,j=0;
//初始化树
for(i=0;i<2*ELEMENTCOUNT-1;i++)

{
tree[i].parent=-1;
tree[i].lchild=-1;
tree[i].rchild=-1;
if (i<count)

{
tree[i].wt=WT[i];
}
else

{
tree[i].wt=0;
tree[i].data='N'; //N为新生成的结点
}
}
//开始生成huffman树
for(i=0;i<ELEMENTCOUNT-1;i++) //因为总结点数为2*ELEMENTCOUNT-1,而生成的新结点数为总结点数-初始根结点数,即:2*ELEMENTCOUNT-1-ELEMENTCOUNT=ELEMENTCOUNT-1

{
minWT1=minWT2=1; //1为最大权值
minE1=minE2=0;
//循环找到第1小和第2小的节点,并记住其权值
for(j=0;j<ELEMENTCOUNT+i;j++) //j<ELEMENTCOUNT+i意味着,每次都从0循环至上次新增的节点,用以寻找剩下的根结点

{
if (tree[j].parent==-1 && tree[j].wt<minWT1)

{
minE2=minE1;
minE1=j;

minWT2=minWT1;
minWT1=tree[j].wt;
}
else if (tree[j].parent==-1 && tree[j].wt<minWT2)

{
minE2=j;
minWT2=tree[j].wt;
}
}
//开始生成新的结点,并修改原父结点的下标
tree[ELEMENTCOUNT+i].parent=-1;
tree[ELEMENTCOUNT+i].wt=minWT1+minWT2;
//此处其左子树与右子树对应可以随意,因为其结点肯定要做为其它结点的子结点
tree[ELEMENTCOUNT+i].lchild=minE1;
tree[ELEMENTCOUNT+i].rchild=minE2;
//修改原根结点的父结点
tree[minE1].parent=tree[minE2].parent=ELEMENTCOUNT+i;
}
}

//采用栈的方式消除递归
void Display(hftree & tree)


{
int stack[100];
int top=0;
//根入栈
stack[top]=2*ELEMENTCOUNT-2;
while(top!=-1)

{
int index=stack[top];
top--;
while(index!=-1)

{
cout<<"结点的Data为:"<<tree[index].data<<","<<"结点的权值为:"<<tree[index].wt<<endl;
int left=-1,right=-1;
//寻找左节点和右节点
for(int i=0;i<2*ELEMENTCOUNT-1;i++)

{
if (tree[i].parent==index)

{
if (left==-1)

{
left=i;
}
else

{
right=i;
break;
}
}
}
if (left==-1 && right==-1)

{
index=-1;
}
else

{
index=left;
top++;
stack[top]=right;
}
}
}
}

int main(int argc, char* argv[])


{
hftree tree;
float WT[ELEMENTCOUNT];

tree[0].data='A';
WT[0]=0.1f;
tree[1].data='B';
WT[1]=0.2f;
tree[2].data='C';
WT[2]=0.3f;
tree[3].data='D';
WT[3]=0.2f;
tree[4].data='E';
WT[4]=0.2f;

huffman(ELEMENTCOUNT,WT,tree);
Display(tree);

return 0;
}
一点说明:为什么在标题中要嵌入英文?原因是为了能够让国外的网友能查询到这篇文章。平常在Google上查资料的时候,经常参考国外网友的博客,帮助我解决了很多问题,所以我也想让他们能够参考我写的内容。当然文中我不可能全部译为英文,所以我尽量把代码粘全,靠代码说话吧。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· C++代码改造为UTF-8编码问题的总结
· DeepSeek 解答了困扰我五年的技术问题
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 用 C# 插值字符串处理器写一个 sscanf
· Java 中堆内存和栈内存上的数据分布和特点
· What?废柴, 还在本地部署DeepSeek吗?Are you kidding?
· 程序员转型AI:行业分析
· 深入集成:使用 DeepSeek SDK for .NET 实现自然语言处理功能
· 为DeepSeek添加本地知识库
· .NET程序员AI开发基座:Microsoft.Extensions.AI