首先我们看看它的原理。
过程很简单
1:首先定义结构体
/* *************huffman code的实现**************** */
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
typedef struct{
float weight;
int parent,lchild,rchild;
char value;
}Node;//定义结构体,value储存字符本身,weight表示权值。
int n;//叶子结点的个数
Node *tree;//树的指针
2:根据输入的n创建相应的2*n-1个结点,并进行处理。
void CreateTree()
{
int i;
printf("-----------------welcome to the super huffmancode------------------\n");
printf("please enter the number of the words:\n");
scanf("%d",&n);
printf("please enter the word and it's weight(such as A 12.3):\n");
tree=(Node*)malloc(sizeof(Node)*(2*n-1));
for(i=0;i<n;i++)
{
getchar();//吸收回车
scanf("%c%f",&tree[i].value,&tree[i].weight);
tree[i].parent=tree[i].lchild=tree[i].rchild=-1;
}//叶子结点处理完毕
for(;i<2*n-1;i++){
tree[i].weight=0;
tree[i].parent=tree[i].lchild=tree[i].rchild=-1;
}//接着处理其余结点
CombineNode();
}
原理就是根据输入的n申请内存(都假设申请成功,并未判断是否成功),接着处理前面n个结点,前面n个叶子结点的权值由用户输入,后面的结点的权值都为0,并且初始化全部结点的双亲结点以及孩子结点都为-1.4:接着进入CombineNode函数将结点的关系梳理出来。
void CombineNode()//结合两结点,供建树使用
{
int i,j,x1,x2,m1,m2;//x1,x2分别储存最小的两个权值的结点的下标,m1,m2分别为所对应的权值。
for(i=0;i<n-1;i++)//一共有n个结点,需要连接n-1次,这也是为什么其余的结点为n-1个的原因,用来做bond
{
m1=m2=1000000;//先假设权值都为一个非常大的值,并且x1,x2随意取
x1=x2=0;
for(j=0;j<n+i;j++)//最开始是从前面n个中选出两个最小的,后面随着后续加入使用的连接结点的增多,慢慢扩大为从n+i个中选出最小的两个,但是所选用的两个结点必须是没用父亲结点的结点,所以if判断中还有一个tree[j].parent==-1.
{
if(tree[j].weight<m1&&tree[j].parent==-1)
{
m2=m1;
x2=x1;
m1=tree[j].weight;
x1=j;
}
else if(tree[j].weight<m2&&tree[j].parent==-1)
{
m2=tree[j].weight;
x2=j;
}
}
tree[x1].parent = n+i;//经过一个小循环(j所控制的循环),就能选出两个没有父亲结点且权值最小的结点用第n+i个结点进行连接
tree[x2].parent = n+i;
tree[n+i].weight = tree[x1].weight + tree[x2].weight;
tree[n+i].lchild = x2;
tree[n+i].rchild = x1;
}
}
char ** encode()
{
char **p,*temp;//temp用来临时存放每个字符所对应的编码
int i,j,start,c,f;//i,j循环变量,start用来记录每个字符的编码所在的起始位置,毕竟不是每个字符的编码都是n个长度。
temp=(char*)malloc(sizeof(char)*n);//申请temp的内存,仅需要n个char的空间即可。
temp[n-1]='\0';//让temp有个结尾字符
p=(char**)malloc(sizeof(char*)*n);//p是指向一堆字符指针的指针,它最后的元素是指向每个不同字符所对应编码的首字符。例如,p[0]就是第0个字符的编码的首字符。
for(i=0;i<n;i++){//前面n个结点均是叶子结点,所以直接从i=0到i=n-1的结点往根找,直到到一个没有父亲结点的结点,也就是根结点
start=n-1;//最初让start处在刚刚设立结尾字符的位置
for(c=i,f=tree[i].parent;f!=-1;c=f,f=tree[f].parent)
if(tree[f].lchild==c) temp[--start]='0';//不停的判断,如果是左孩子则先让start-1,再赋值为0
else temp[--start]='1';//否则就是赋值为1
p[i]=(char*)malloc((n-start)*sizeof(char));//依据刚才所走过的路径长度申请内存,并让最初申请的p的元素指向该段内存
strcpy(p[i],&temp[start]);//此时start就正好是字符所对应编码的起始位置,直接将temp储存的编码复制给p[i]对应内存中
}
free(temp);//释放中间申请的临时储存字符编码的内存
return p;
}
6:main函数如下
int main()
{
int i;
char **p;
CreateTree();
p=encode();
printf("Finished processing.........................\n");
for(i=0;i<n;i++)//输出huffman 编码
{
printf("%c's huffmancode is %s\n",tree[i].value,p[i]);
}
return 0;
}
总代码如下:/* *************huffman code的实现**************** */
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
typedef struct{
float weight;
int parent,lchild,rchild;
char value;
}Node;//定义结构体,value储存字符本身,weight表示权值。
int n;//叶子结点的个数
Node *tree;//树的指针
void CombineNode()//结合两结点,供建树使用
{
int i,j,x1,x2,m1,m2;//x1,x2分别储存最小的两个权值的结点的下标,m1,m2分别为所对应的权值。
for(i=0;i<n-1;i++)
{
m1=m2=1000000;
x1=x2=0;
for(j=0;j<n+i;j++)
{
if(tree[j].weight<m1&&tree[j].parent==-1)
{
m2=m1;
x2=x1;
m1=tree[j].weight;
x1=j;
}
else if(tree[j].weight<m2&&tree[j].parent==-1)
{
m2=tree[j].weight;
x2=j;
}
}
tree[x1].parent = n+i;
tree[x2].parent = n+i;
tree[n+i].weight = tree[x1].weight + tree[x2].weight;
tree[n+i].lchild = x2;
tree[n+i].rchild = x1;
}
}
void CreateTree()
{
int i;
printf("-----------------welcome to the super huffmancode------------------\n");
printf("please enter the number of the words:\n");
scanf("%d",&n);
printf("please enter the word and it's weight(such as A 12.3):\n");
tree=(Node*)malloc(sizeof(Node)*(2*n-1));
for(i=0;i<n;i++)
{
getchar();//吸收回车
scanf("%c%f",&tree[i].value,&tree[i].weight);
tree[i].parent=tree[i].lchild=tree[i].rchild=-1;
}//叶子结点处理完毕
for(;i<2*n-1;i++){
tree[i].weight=0;
tree[i].parent=tree[i].lchild=tree[i].rchild=-1;
}//接着处理其余结点
CombineNode();
}
char ** encode()
{
char **p,*temp;
int i,j,start,c,f;
temp=(char*)malloc(sizeof(char)*n);
temp[n-1]='\0';
p=(char**)malloc(sizeof(char*)*n);
for(i=0;i<n;i++){
start=n-1;
for(c=i,f=tree[i].parent;f!=-1;c=f,f=tree[f].parent)
if(tree[f].lchild==c) temp[--start]='0';
else temp[--start]='1';
p[i]=(char*)malloc((n-start)*sizeof(char));
strcpy(p[i],&temp[start]);
}
free(temp);
return p;
}
int main()
{
int i;
char **p;
CreateTree();
p=encode();
printf("Finished processing.........................\n");
for(i=0;i<n;i++)
{
printf("%c's huffmancode is %s\n",tree[i].value,p[i]);
}
return 0;
}
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
typedef struct{
float weight;
int parent,lchild,rchild;
char value;
}Node;//定义结构体,value储存字符本身,weight表示权值。
int n;//叶子结点的个数
Node *tree;//树的指针
void CombineNode()//结合两结点,供建树使用
{
int i,j,x1,x2,m1,m2;//x1,x2分别储存最小的两个权值的结点的下标,m1,m2分别为所对应的权值。
for(i=0;i<n-1;i++)
{
m1=m2=1000000;
x1=x2=0;
for(j=0;j<n+i;j++)
{
if(tree[j].weight<m1&&tree[j].parent==-1)
{
m2=m1;
x2=x1;
m1=tree[j].weight;
x1=j;
}
else if(tree[j].weight<m2&&tree[j].parent==-1)
{
m2=tree[j].weight;
x2=j;
}
}
tree[x1].parent = n+i;
tree[x2].parent = n+i;
tree[n+i].weight = tree[x1].weight + tree[x2].weight;
tree[n+i].lchild = x2;
tree[n+i].rchild = x1;
}
}
void CreateTree()
{
int i;
printf("-----------------welcome to the super huffmancode------------------\n");
printf("please enter the number of the words:\n");
scanf("%d",&n);
printf("please enter the word and it's weight(such as A 12.3):\n");
tree=(Node*)malloc(sizeof(Node)*(2*n-1));
for(i=0;i<n;i++)
{
getchar();//吸收回车
scanf("%c%f",&tree[i].value,&tree[i].weight);
tree[i].parent=tree[i].lchild=tree[i].rchild=-1;
}//叶子结点处理完毕
for(;i<2*n-1;i++){
tree[i].weight=0;
tree[i].parent=tree[i].lchild=tree[i].rchild=-1;
}//接着处理其余结点
CombineNode();
}
char ** encode()
{
char **p,*temp;
int i,j,start,c,f;
temp=(char*)malloc(sizeof(char)*n);
temp[n-1]='\0';
p=(char**)malloc(sizeof(char*)*n);
for(i=0;i<n;i++){
start=n-1;
for(c=i,f=tree[i].parent;f!=-1;c=f,f=tree[f].parent)
if(tree[f].lchild==c) temp[--start]='0';
else temp[--start]='1';
p[i]=(char*)malloc((n-start)*sizeof(char));
strcpy(p[i],&temp[start]);
}
free(temp);
return p;
}
int main()
{
int i;
char **p;
CreateTree();
p=encode();
printf("Finished processing.........................\n");
for(i=0;i<n;i++)
{
printf("%c's huffmancode is %s\n",tree[i].value,p[i]);
}
return 0;
}