主题:敬请赐教
自律自强
[专家分:0] 发布于 2006-10-16 19:46:00
各位高手:
赫夫曼编码怎么用程序代码实现啊?初学数据结构真的感觉很茫然,可以说说你们的经验吗?望各位不吝赐教,感激不尽![em12]
板凳
xieyong456 [专家分:2620] 发布于 2006-10-17 14:36:00
//望你兴叹
/*编辑器devcpp*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct
{
unsigned int weight;/*放权值*/
unsigned int parent;/*父亲结点*/
unsigned int lchild;/*左孩子*/
unsigned int rchild;/*右孩子*/
}HTNode, *HuffmanTree; /*动态申请赫夫曼树*/
typedef char **HuffmanCode;/*动态分配赫夫曼表*/
void CreateHuffmanTree(HuffmanTree *HT, unsigned int *w , int n);
void Select(HuffmanTree HT, int t, int *s1, int *s2);
void HuffmanCoding(HuffmanTree HT, HuffmanCode *HC, int n);
void PrintHuffmanCode(HuffmanCode HC, unsigned int *w, int n);
int main(void)
{
HuffmanTree HT;
HuffmanCode HC;
int i, n;
unsigned int *w;
printf("请输入叶子结点数 : ");
scanf("%d", &n);
w = (unsigned int *)malloc(n * sizeof(unsigned int));
printf("请输入各个叶子结点的权值 : \n");
for(i = 0; i < n; i++)
{
scanf("%d", &w[i]);
}
CreateHuffmanTree(&HT, w, n);
HuffmanCoding(HT, &HC, n);
PrintHuffmanCode(HC, w, n);
getch();
}
/*****************************
建立赫夫曼树,w存放权值,在每次
把两个小的权值相加后,在每次
select中都能包括进去新的结点
每次父亲结点被重新赋值,不为0
在每次select中除去
*****************************/
void CreateHuffmanTree(HuffmanTree *HT, unsigned int *w , int n)
{
int i, m;
int s1, s2;
char *cd;
m = 2 * n - 1; /*总结点数*/
*HT = (HuffmanTree)malloc((m + 1) * sizeof(HTNode));
for(i = 1; i <= n; ++i, ++w) /*叶子结点初试化*/
{
(*HT)[i].weight = *w;
(*HT)[i].parent = 0;
(*HT)[i].lchild = 0;
(*HT)[i].rchild = 0;
}
for(; i <= m; ++i)
{
(*HT)[i].weight = 0;
(*HT)[i].parent = 0;
(*HT)[i].lchild = 0;
(*HT)[i].rchild = 0;
}
for(i = n + 1; i <= m; ++i)
{
Select(*HT, i - 1, &s1, &s2);/*从权值中选两个最小的*/
(*HT)[s1].parent = i; /*父亲结点都被赋值,在select循环中可以除去*/
(*HT)[s2].parent = i;
(*HT)[i].lchild = s1; /*孩子结点被赋值*/
(*HT)[i].rchild = s2;
(*HT)[i].weight = (*HT)[s1].weight + (*HT)[s2].weight;/*加后成新结点*/
}
}
/*寻找两个最小的结点s1, s2*/
void Select(HuffmanTree HT, int t, int *s1, int *s2)
{
int m, n, i;
m = n = 10000;/*感觉有点取巧可以自己修改*/
for(i = 1; i <= t; i++)/*遍历找两个最小的结点*/
{
if(HT[i].parent == 0 /*m和n只是一个穿插的过程*/
&& (HT[i].weight < m || HT[i].weight < n))
{
if(m < n) /*把大的除去,小的继续比较放那里*/
{
n = HT[i].weight;
*s2 = i;
}
else
{
m = HT[i].weight;
*s1 = i;
}
}
}
if(*s1 > *s2) /*把小的放前面*/
{
i = *s1;
*s1 = *s2;
*s2 = i;
}
}
/*赫夫曼编码,放入HC中*/
void HuffmanCoding(HuffmanTree HT, HuffmanCode *HC, int n)
{
int i, start, c, f;
char *cd;
(*HC) = (HuffmanCode )malloc((n + 1) * sizeof(char *));
cd = (char *)malloc(n * sizeof(char));/*编码的空间*/
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].lchild == c)
{
cd[--start] = '0';
}//if
else
{
cd[--start] = '1';
}//else
}//for
/*为第i个叶子结点求空间*/
(*HC)[i] = (char *)malloc((n - start) * sizeof(char));
strcpy((*HC)[i], &cd[start]); /*从cd复制到HC*/
}//for
}
/*打印编码*/
void PrintHuffmanCode(HuffmanCode HC, unsigned int *w, int n)
{
int i;
printf("HuffmanCode 是 : \n");
for(i = 1; i <= n; i++)
{
printf("%3d---", w[i - 1]); /*先打印权值*/
puts(HC[i]); /*打印表*/
printf("\n");
}
}