//************************************
//本程序演示内容如下:
//1.哈弗曼编码[最优二叉树,采用顺序存储结构]
//2.二级指针使用
//3.函数内部使用malloc注意
//zping 2012-3-17
//************************************
#include<string.h>
#include<stdlib.h>
#include<stdio.h>
int m,s1,s2;
typedef struct
{ int weight;
int parent,lchild,rchild;
}HuffmanTree;
void Select(HuffmanTree *HT,int n) //选择最小两个权值的结点序号分别放在s1和s2
{
int i,flag=0;
for(i = 1;i <= n;i++)
{
if((!HT[i].parent) && (!flag))
{
s1=i;
flag=1;
continue;
}
if(HT[s1].weight>HT[i].weight && (!HT[i].parent))
s1=i;
}
flag=0;
for(i=1;i<=n;i++)
{
if((!HT[i].parent) && (!flag) && (i!=s1))
{
s2=i;
flag=1;
continue;
}
if(HT[s2].weight>HT[i].weight && (!HT[i].parent) && (i!=s1))
s2=i;
}
}
char **HuffmanCoding(HuffmanTree *HT, char **HC, int *w, int n) //构造函数建哈夫曼树并逆序构造编码
{
int i;
char *cd;
int f,start,c;
if(n<=1) return NULL; //若结点只有一个,则返回
m = 2 * n - 1; //计算总共节点个数
HT = (HuffmanTree *)malloc((m+1) * sizeof(HuffmanTree));//给各个节点分配空间,下标从1开始所以多分配一个。
for (i=1; i<=n; i++) //初始化结点空间
{
HT[i].weight=w[i-1];
HT[i].parent=0;
HT[i].lchild=0;
HT[i].rchild=0;
}
for (i=n+1; 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);
HT[s1].parent = i; HT[s2].parent = i;
HT[i].lchild = s1; HT[i].rchild = s2;
HT[i].weight = HT[s1].weight + HT[s2].weight;
}
//构造哈夫曼编码
HC=(char **)malloc((n+1)*sizeof(char *)); //分配一个空间存储n个编码字符串的指针(多分配一个)
cd=(char*)malloc((n+1)*sizeof(char)); //分配一个临时空间存储当前一个叶子节点的编码(多分配一个)
cd[n-1]='\0'; //从右向左逐位存放逆序编码[最终便是从左向右的顺序编码],首先存放编码结束符
for(i=1;i<=n;i++) //开始求编码
{
start=n-1; //初始化编码起始指针
c=i;
f=HT[i].parent;
while(f!=0)
{
if( HT[f].lchild == c)
cd[--start]='0'; //左分支标0
else
cd[--start]='1'; //右分支标1
c=f;
f=HT[f].parent;
HC[i]=(char *)malloc((n-start)*sizeof(char)); //为第i个编码分配空间
strcpy(HC[i],&cd[start]);
}
}
free(cd);
return HC; //此处要注意,本身HC是一个二级指针,在函数内部使用malloc分配了空间所以要返回该指针这是值传递;
//也可以使用三级指针采用引用传递,这时则不用返回了
}
int main(void)
{
HuffmanTree *HT;
char **HC;
int i, n=4;
char chr[]={'a','b','c','d'};
int w[] = {7,5,2,4};
HC=HuffmanCoding(HT,HC,w,n);
printf("The HuffmanCode is:\n");
for(i = 1;i <= n;i++)
printf("%2d%5c%4d: %s\n",i,chr[i-1],w[i-1],HC[i]);
return 0;
}
//本程序演示内容如下:
//1.哈弗曼编码[最优二叉树,采用顺序存储结构]
//2.二级指针使用
//3.函数内部使用malloc注意
//zping 2012-3-17
//************************************
#include<string.h>
#include<stdlib.h>
#include<stdio.h>
int m,s1,s2;
typedef struct
{ int weight;
int parent,lchild,rchild;
}HuffmanTree;
void Select(HuffmanTree *HT,int n) //选择最小两个权值的结点序号分别放在s1和s2
{
int i,flag=0;
for(i = 1;i <= n;i++)
{
if((!HT[i].parent) && (!flag))
{
s1=i;
flag=1;
continue;
}
if(HT[s1].weight>HT[i].weight && (!HT[i].parent))
s1=i;
}
flag=0;
for(i=1;i<=n;i++)
{
if((!HT[i].parent) && (!flag) && (i!=s1))
{
s2=i;
flag=1;
continue;
}
if(HT[s2].weight>HT[i].weight && (!HT[i].parent) && (i!=s1))
s2=i;
}
}
char **HuffmanCoding(HuffmanTree *HT, char **HC, int *w, int n) //构造函数建哈夫曼树并逆序构造编码
{
int i;
char *cd;
int f,start,c;
if(n<=1) return NULL; //若结点只有一个,则返回
m = 2 * n - 1; //计算总共节点个数
HT = (HuffmanTree *)malloc((m+1) * sizeof(HuffmanTree));//给各个节点分配空间,下标从1开始所以多分配一个。
for (i=1; i<=n; i++) //初始化结点空间
{
HT[i].weight=w[i-1];
HT[i].parent=0;
HT[i].lchild=0;
HT[i].rchild=0;
}
for (i=n+1; 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);
HT[s1].parent = i; HT[s2].parent = i;
HT[i].lchild = s1; HT[i].rchild = s2;
HT[i].weight = HT[s1].weight + HT[s2].weight;
}
//构造哈夫曼编码
HC=(char **)malloc((n+1)*sizeof(char *)); //分配一个空间存储n个编码字符串的指针(多分配一个)
cd=(char*)malloc((n+1)*sizeof(char)); //分配一个临时空间存储当前一个叶子节点的编码(多分配一个)
cd[n-1]='\0'; //从右向左逐位存放逆序编码[最终便是从左向右的顺序编码],首先存放编码结束符
for(i=1;i<=n;i++) //开始求编码
{
start=n-1; //初始化编码起始指针
c=i;
f=HT[i].parent;
while(f!=0)
{
if( HT[f].lchild == c)
cd[--start]='0'; //左分支标0
else
cd[--start]='1'; //右分支标1
c=f;
f=HT[f].parent;
HC[i]=(char *)malloc((n-start)*sizeof(char)); //为第i个编码分配空间
strcpy(HC[i],&cd[start]);
}
}
free(cd);
return HC; //此处要注意,本身HC是一个二级指针,在函数内部使用malloc分配了空间所以要返回该指针这是值传递;
//也可以使用三级指针采用引用传递,这时则不用返回了
}
int main(void)
{
HuffmanTree *HT;
char **HC;
int i, n=4;
char chr[]={'a','b','c','d'};
int w[] = {7,5,2,4};
HC=HuffmanCoding(HT,HC,w,n);
printf("The HuffmanCode is:\n");
for(i = 1;i <= n;i++)
printf("%2d%5c%4d: %s\n",i,chr[i-1],w[i-1],HC[i]);
return 0;
}