#include <stdio.h>
#include <string.h>
#include <stdlib.h><?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
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);
system(“pause”);
}
/*****************************
建立赫夫曼樹,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");
}
}