函数模块
哈夫曼树的定义
typedef struct {
int weight, parent, lc, rc;//权值,双亲,左孩子,右孩子
}HTNode,*HuffmanTree;
typedef char** HuffmanCode;//为存储哈夫曼编码的数组做准备.后期传入参数为指针,不妨直接定义在这里
选择最小、次小权值
void Select(HuffmanTree HT, int n,int &s1, int &s2)//选择最小和次小权值编号的函数
{
//擂台法选择两值
s1 = 0; s2 = 0;//最小、次小权值对应编号为s1,s2
int m1 = 100; int m2 = 100; int i;//最小、次小权值为m1,m2
for (i = 1; i <= n; i++)
{
if (HT[i].parent == 0)
{
if (HT[i].weight < m1)
{
m2 = m1;
s2 = s1;
m1 = HT[i].weight;//更新m1的值
s1 = i;
}
else if (HT[i].weight < m2)
{
m2 = HT[i].weight;//更新m2的值
s2 = i;
}
}
}
}
初始化二叉树、创建并打印哈夫曼树、求哈夫曼编码并打印
void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,int *w, int n)
{
//初始化二叉树
if (n <= 1) return; int m = 2 * n - 1;//n个叶子结点的二叉树有2n-1个结点
int i; HuffmanTree p = HT;
HT = (HuffmanTree)malloc((m+1)*sizeof(HTNode));//为哈夫曼树分配存储空间;m+1而非m是因为0号位闲置
for (p = HT + 1, i = 1; i <= n; ++i, ++p, ++w)
{
p->weight = *w;
p->parent = 0;
p->lc= 0;
p->rc = 0;
}
for (; i <= m; ++i, ++p)
{
p->weight = 0;
p->parent = 0;
p->lc= 0;
p->rc= 0;
}
/*等价于for (i = 1; i <= n; ++i)
{
HT[i].weight = w[i - 1];
HT[i].lc = 0;
HT[i].rc = 0;
HT[i].parent = 0;
}
for (; i <= m; ++i, ++p)
{
HT[i].weight =0;
HT[i].lc = 0;
HT[i].rc = 0;
HT[i].parent = 0;
}*/
//创建哈夫曼树
int s1,s2;
for (i = n + 1; i <= m; i++)
{
Select(HT,i-1,s1,s2);
HT[s1].parent = i;
HT[s2].parent = i;
HT[i].lc = s1;
HT[i].rc = s2;
HT[i].weight = HT[s1].weight + HT[s2].weight;
}
printf("创建哈夫曼树如下\n");
printf("NUM weight parent lc rc \n");
for (i = 1; i <= m; i++)
{
printf("HT[%2d] %6d %6d %6d %6d\n", i, HT[i].weight, HT[i].parent, HT[i].lc, HT[i].rc);
}
printf("\n");
//求哈夫曼编码
int c,start,f; char* cd;
HC = (HuffmanCode)malloc((n + 1) * sizeof(char*));
cd = (char*)malloc(n * sizeof(char)); //cd为临时字符数组
cd[n - 1] = '\0';
for (i = 1; i <= n; ++i)
{
start = n - 1;
for (c = i, f = HT[i].parent; f != 0; c = f, f = HT[f].parent)
{
if (HT[f].lc == c)
{
start--;
cd[start] = '0';
}
else
{
start--;
cd[start] = '1';
}
}
HC[i] = (char*)malloc((n - start) * sizeof(char));
strcpy_s(HC[i],n-start+1, &cd[start]);
}
free(cd);
printf("哈夫曼编码如下\n");
for (i = 1; i <= N; i++)
{
printf("HT[%d]编码为\n",i);
puts(HC[i]);
}
}
上级实现
完整代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 8
typedef struct {
int weight, parent, lc, rc;//权值,双亲,左孩子,右孩子
}HTNode,*HuffmanTree;
typedef char** HuffmanCode;//为存储哈夫曼编码的数组做准备.后期传入参数为指针,不妨直接定义在这里
void Select(HuffmanTree HT, int n,int &s1, int &s2)//选择最小和次小权值编号的函数
{
//擂台法选择两值
s1 = 0; s2 = 0;//最小、次小权值对应编号为s1,s2
int m1 = 100; int m2 = 100; int i;//最小、次小权值为m1,m2
for (i = 1; i <= n; i++)
{
if (HT[i].parent == 0)
{
if (HT[i].weight < m1)
{
m2 = m1;
s2 = s1;
m1 = HT[i].weight;//更新m1的值
s1 = i;
}
else if (HT[i].weight < m2)
{
m2 = HT[i].weight;//更新m2的值
s2 = i;
}
}
}
}
void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,int *w, int n)
{
//初始化二叉树
if (n <= 1) return; int m = 2 * n - 1;//n个叶子结点的二叉树有2n-1个结点
int i; HuffmanTree p = HT;
HT = (HuffmanTree)malloc((m+1)*sizeof(HTNode));//为哈夫曼树分配存储空间;m+1而非m是因为0号位闲置
for (p = HT + 1, i = 1; i <= n; ++i, ++p, ++w)
{
p->weight = *w;
p->parent = 0;
p->lc= 0;
p->rc = 0;
}
for (; i <= m; ++i, ++p)
{
p->weight = 0;
p->parent = 0;
p->lc= 0;
p->rc= 0;
}
/*等价于for (i = 1; i <= n; ++i)
{
HT[i].weight = w[i - 1];
HT[i].lc = 0;
HT[i].rc = 0;
HT[i].parent = 0;
}
for (; i <= m; ++i, ++p)
{
HT[i].weight =0;
HT[i].lc = 0;
HT[i].rc = 0;
HT[i].parent = 0;
}*/
//创建哈夫曼树
int s1,s2;
for (i = n + 1; i <= m; i++)
{
Select(HT,i-1,s1,s2);
HT[s1].parent = i;
HT[s2].parent = i;
HT[i].lc = s1;
HT[i].rc = s2;
HT[i].weight = HT[s1].weight + HT[s2].weight;
}
printf("创建哈夫曼树如下\n");
printf("NUM weight parent lc rc \n");
for (i = 1; i <= m; i++)
{
printf("HT[%2d] %6d %6d %6d %6d\n", i, HT[i].weight, HT[i].parent, HT[i].lc, HT[i].rc);
}
printf("\n");
//求哈夫曼编码
int c,start,f; char* cd;
HC = (HuffmanCode)malloc((n + 1) * sizeof(char*));
cd = (char*)malloc(n * sizeof(char)); //cd为临时字符数组
cd[n - 1] = '\0';
for (i = 1; i <= n; ++i)
{
start = n - 1;
for (c = i, f = HT[i].parent; f != 0; c = f, f = HT[f].parent)
if (HT[f].lc == c) cd[--start] = '0';
else cd[--start] = '1';
HC[i] = (char*)malloc((n - start) * sizeof(char));
strcpy_s(HC[i],n-start+1, &cd[start]);
}
free(cd);
printf("哈夫曼编码如下\n");
for (i = 1; i <= N; i++)
{
printf("HT[%d]编码为\n",i);
puts(HC[i]);
}
}
int main(void)
{
HuffmanTree HT; HuffmanCode HC; int w[N];
printf("输入叶子结点的值\n"); int i;
for (i = 0; i < N; i++)
{
scanf_s("%d",&w[i]);
}
HuffmanCoding(HT,HC, w, N);
return 0;
}
运行结果