文章目录
- 赫夫曼树的建立
- 思路
- 如图所示
- 大致思路:
- 构造步骤
- 借助一个结构体数组存储这个赫夫曼树,结构体中包含权重,双亲的数组下标,左孩子的数组下标,右孩子的数组下标,一个标志节点是否已被建造的flag(直接用双亲判断也可以);
- 1.先初始化这个赫夫曼树:
- 将结构体中所有的数据赋予0值。
- 2.创造赫夫曼树(借助一个函数寻找最小权重的两个节点):
- 从第n+1个数组位置开始创建用来链接两个叶子节点的“根节点”,在创建每一个“根节点”时,要,将两个叶子节点的双亲的数组下标存入(也就是当前这个根节点的下标),要存储“根节点”的权重,左右孩子的数组下标;在寻找最小权重的两个叶子节点的函数中,每找到一个节点时,记得将这个节点的flag值改为1,便于后续查找剩余节点中的最小节点时,可以跳过这个节点。
- 3.遍历输出赫夫曼树
- 很简单,直接将数组的每一位输出即可。
赫夫曼树的建立
#define _CRT_SECURE_NO_WARNINGS 1
#pragma warning(disable:6031)
#include<stdio.h>
#include<stdlib.h>
#define N 15
#define M 2*N-1
typedef struct node
{
char data;//存的数据
int weight;//权重
int parent;//双亲的数组下标
int lchild;//左孩子的数组下标
int rchild;//右孩子的数组下标
int flag;//标志这个节点是否已经被查找到,并构造成树过
} Hffmantree;//
int select(Hffmantree* H, int n);//查找剩余未被构造成数的节点中权重最小的节点
void init_H(Hffmantree* H, int n);//初始化赫夫曼树
void create_H(Hffmantree* H, int n);//创建赫夫曼树
void traverse_H(Hffmantree* H, int n);//遍历输出赫夫曼树
int main()
{
int n;
printf("请输入该赫夫曼树的叶子节点个数:");
scanf("%d", &n);//便于区分已有的叶子节点下标和新创建的“根节点”的数组下标
Hffmantree H[M+1];
int i;
for (i = 1; i <= n; i++)
{
H[i].data = 64 + i;
H[i].weight = i;
}//存入赫夫曼树节点的数据'A','B','C','D'......
for (i = n+1; i <= 2*n-1; i++)
{
H[i].data = ' ';
}
init_H(H, n);
traverse_H(H, n);//输出一次初始化的赫夫曼树
create_H(H, n);
traverse_H(H, n);//输出一次构造好的赫夫曼树
}
void init_H(Hffmantree *H, int n)
{
int i = 0;
for (i = 1; i <= n; i++)
{
H[i].parent = 0;
H[i].lchild = 0;
H[i].rchild = 0;
H[i].flag = 0;
}//初始化原本的叶子节点
for (i = n + 1; i <= 2 * n - 1; i++)
{
H[i].weight = 0;
H[i].parent = 0;
H[i].lchild = 0;
H[i].rchild = 0;
H[i].flag = 0;
}//初始化将要构造的“根节点”
}
int select(Hffmantree* H, int n)
{
int i = 0;
int min=0;//存放权重最小节点的权重值
int dex=0;//存放权重最小的节点的下标
for (i = 0; i <= n; i++)
{
if (H[i].flag == 0)
{
min = H[i].weight;
dex = i;
break;
}
}//为避免min和dex值不合理,用一个for循环找到第一个为被查找到过的节点的下标和权重作为min和dex的初始化值
for (i = 0; i <= n; i++)
{
if (H[i].flag == 0)
{
if (H[i].weight < min)
{
min = H[i].weight;
dex = i;
}
}
}//找到最小权重的节点的权重值和下标
H[dex].flag = 1;//改写flag为1,标志该结点已被查找过
return dex;//返回最小权重节点的下标
}
void create_H(Hffmantree* H, int n)
{
int i = n + 1;
for (i = n + 1; i <= 2 * n - 1; i++)//从结构体数组的第n-1位开始创建“根节点”
{
int a;
a = select(H, i - 1);//查找当前最小权值的节点下标
int b;
b = select(H, i - 1);//查找第二小权值的节点下标(当然它也就是查找完最小权值节点之后最小的权值节点)
H[i].weight = H[a].weight + H[b].weight;//存储“根节点”的权重
H[i].lchild = a;//存储“根节点”的左孩子下标
H[i].rchild = b;//存储“根节点”的右孩子下标
H[a].parent = i;//将左孩子的双亲下标存入
H[b].parent = i;//将右孩子的双亲下标存入
}
}
void traverse_H(Hffmantree* H, int n)
{
int i = 0;
printf("当前的赫夫曼树:\n");
for (i = 1; i <= 2 * n - 1; i++)
{
printf("%d %c %d %d %d %d %d \n",i, H[i].data, H[i].weight, H[i].parent, H[i].lchild, H[i].rchild, H[i].flag);
}//遍历输出
printf("\n");
}
思路
-------------------------------从一个博主那里顺来的百度图片(感谢万分)--------------------------------------