有关huffman编码的编程问题
代码如下:#include <stdio.h>
#include <stdlib.h>
#define MaxValue 10000 //设定的权值最大值
#define MaxN 100 //设定的最大结点个数
#include "Haffman.h" //包含头文件"Haffman.h"
void main(void)
{
int i, j, n; //定义n为结点个数
int weight[MaxN]; //存放各个结点的权值
//输入结点个数n
printf("请输入结点个数(不能超过%d):", MaxN);
scanf("%d", &n);
//判断n的值,最大不能超过MaxN
if(n > MaxN)
{
printf("\n给出的n越界,修改MaxN的值!\n");
exit(0);
}
//输入各个结点的权值
printf("\n请输入各个结点的权值:\n");
for(i = 0; i < n; i++)
{
printf("weight[%d] = ", i + 1);
scanf("%d", &weight[i]);
}
HaffNode *myHaffTree = (HaffNode *)malloc(sizeof(HaffNode) * (2 * n + 1));
Code *myHaffCode = (Code *)malloc(sizeof(Code) * n);
Haffman(weight, n, myHaffTree);
HaffmanCode(myHaffTree, n, myHaffCode);
//输出每个叶结点的哈夫曼编码
printf("\n哈夫曼编码结果如下:\n");
for(i = 0; i < n; i++)
{
printf("Weight = %d Code = ", myHaffCode[i].weight);
for(j = myHaffCode[i].start; j < n; j++)
printf("%d", myHaffCode[i].bit[j]);
putchar('\n');
}
putchar('\n');
}
头文件 huffman.h 如下:
typedef struct
{
int weight; //权值
int flag; //标记
int parent; //双亲结点下标
int leftChild; //左孩子下标
int rightChild; //右孩子下标
}HaffNode; //哈夫曼树的结点结构
typedef struct
{
int bit[MaxN]; //数组
int start; //编码的起始下标值
int weight; //字符的权值
}Code; //哈夫曼编码的结构
void Haffman(int weight[], int n, HaffNode haffTree[])
//建立叶结点的个数为n权值数组为weight的哈夫曼树haffTree
{
int i, j, m1, m2, x1, x2;
//哈夫曼树haffTrdd初始化。n个叶结点的二叉树共有2n-1个结点
for(i = 0; i < 2 * n - 1; i++)
{
if(i < n)
haffTree[i].weight = weight[i];
else haffTree[i].weight = 0;
haffTree[i].parent = -1;
haffTree[i].flag = 0;
haffTree[i].leftChild = -1;
haffTree[i].rightChild = -1;
}
//构造哈夫曼树haffTree的n-1个非叶结点
for(i = 0; i < n - 1; i++)
{
m1 = m2 = MaxValue;
x1 = x2 = 0;
for(j = 0; j < n + i; j++)
{
if(haffTree[j].weight < m1 && haffTree[j].flag == 0)
{
m2 = m1;
x2 = x1;
m1 = haffTree[j].weight;
x1 = j;
}
else if(haffTree[j].weight < m2 && haffTree[j].flag == 0)
{
m2 = haffTree[j].weight;
x2 = j;
}
}
//将找出的两颗权值最小的子树合并为一颗子树
haffTree[x1].parent = n + i;
haffTree[x2].parent = n + i;
haffTree[x1].flag = 1;
haffTree[x2].flag = 1;
haffTree[n + i].weight = haffTree[x1].weight + haffTree[x2].weight;
haffTree[n + i].leftChild = x1;
haffTree[n + i].rightChild = x2;
}
}
void HaffmanCode(HaffNode haffTree[], int n, Code haffCode[])
//由n个结点的哈夫曼树haffTree构造哈夫曼编码haffCode
{
Code *cd = (Code *)malloc(sizeof(Code));
int i, j, child, parent;
//求n个叶结点的哈夫曼编码
for(i = 0; i < n; i++)
{
cd ->start = n - 1; //不等长编码的最后一位为n-1
cd ->weight = haffTree[i].weight; //取得编码对应的权值
child = i;
parent = haffTree[child].parent;
//由叶结点向上直到根结点
while(parent != -1)
{
if(haffTree[parent].leftChild == child)
cd ->bit[cd ->start] = 0; //左孩子分支编码0
else
cd ->bit[cd ->start] = 1; //右孩子分支编码1
cd ->start--;
child = parent;
parent = haffTree[child].parent;
}
for(j = cd ->start + 1; j < n; j++)
haffCode[i].bit[j] = cd ->bit[j]; //保存每个叶结点的编码
haffCode[i].start = cd ->start + 1; //保存叶结点编码的起始位置
haffCode[i].weight = cd ->weight; //保存编码对应的权值
}
}