/*********************************************************** *fiename:HuffmanCode.c *author:于鹏 csdn *modify:dhfalive 2010.11.9 dh_fa@live.cn vs2008 *description:用于生成给定带权重的节点的霍夫曼编码 **********************************************************/ #include <stdio.h> #include <malloc.h> #include <conio.h> #include <string.h> #include <stdlib.h> #define HuffmanTree HF #define HuffmanCode HMC typedef struct { unsigned int weight; //权重 unsigned int parent,lchild,rchild; } HTNode,*HF; typedef char **HMC; typedef struct { unsigned int s1; unsigned int s2; } MinCode; void Error(char *message); HMC HuffmanCoding(HF HT,HMC HC,unsigned int *w,unsigned int n); MinCode Select(HF HT,unsigned int n); int main() { MinCode Select(HF HT,unsigned int n); HF HT=NULL; HuffmanCode HC=NULL; unsigned int *w=NULL; unsigned int i,n; printf("请输入节点数n:"); scanf("%d",&n); w=(unsigned int *)malloc((n+1)*sizeof(unsigned int *)); //权重数组,0索引空间不用 w[0]=0; printf("请输入权重:/n"); for(i=1;i<=n;i++) { printf("w[%d]=",i); scanf("%d",&w[i]); } HC=HuffmanCoding(HT,HC,w,n); printf("HMC:/n"); printf("Number/t/tWeight/t/tCode/n"); for(i=1;i<=n;i++) printf("%d/t/t%d/t/t%s/n",i,w[i],HC[i]); //应该加上这句,HC=(HMC)malloc((n+1)*sizeof(char *));有申请,没有释放 free(HC); system("pause"); return 0; } void Error(char *message) { fprintf(stderr,"Error:%s/n",message); exit(1); } HMC HuffmanCoding(HF HT,HMC HC,unsigned int *w,unsigned int n) { unsigned int i,s1=0,s2=0; HF p; char *cd; unsigned int f,c,start,m; MinCode min; if(n<=1) //节点数目不合法,输出错误信息 Error("Code too small!"); m = 2 * n - 1; //可以保存n个叶子节点的hf的节点总数 HT=(HF)malloc((m+1)*sizeof(HTNode)); //用数组来保存二叉树的信息 //初始化hf,前n个节点作为叶子 for(p=HT,i=0;i<=n;i++,p++,w++) { p->weight=*w; p->parent=0; p->lchild=0; p->rchild=0; } for(;i<=m;i++,p++) { p->weight=0; p->parent=0; p->lchild=0; p->rchild=0; } for(i=n+1;i<=m;i++) //建树 { min=Select(HT,i-1); s1=min.s1; s2=min.s2; 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; } printf("HT List:/n"); printf("Number/t/tweight/t/tparent/t/tlchild/t/trchild/n"); for(i=1;i<=m;i++) printf("%d/t/t%d/t/t%d/t/t%d/t/t%d/n", i,HT[i].weight,HT[i].parent,HT[i].lchild,HT[i].rchild); HC=(HMC)malloc((n+1)*sizeof(char *));//保存各个叶子节点的hfc,0索引不用 cd=(char *)malloc(n*sizeof(char *)); cd[n-1]='/0'; for(i=1;i<=n;i++) //根据建立的hf,构造hfc { 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'; else cd[--start]='1'; HC[i]=(char *)malloc((n-start)*sizeof(char *)); strcpy(HC[i],&cd[start]); } free(cd); return HC; } MinCode Select(HF HT,unsigned int n) //找到还没有父节点的节点中权重最小的两个节点 { unsigned int min,secmin; //分别存放权重最小和第二小的节点的索引 unsigned int temp; unsigned int i,s1,s2,tempi; MinCode code; s1=1; s2=1; for(i=1;i<=n;i++) //找到第一个没有父节点的节点,并保存其索引 if(HT[i].parent==0) { min=HT[i].weight; s1=i; break; } tempi=i++; for(;i<=n;i++) //找出权重最小的那个节点,保存其索引 if(HT[i].weight<min&&HT[i].parent==0) { min=HT[i].weight; s1=i; } //同上,找出权重第二小的那个节点,并保存其索引 for(i=tempi;i<=n;i++) if(HT[i].parent==0&&i!=s1) { secmin=HT[i].weight; s2=i; break; } for(i=1;i<=n;i++) if(HT[i].weight<secmin&&i!=s1&&HT[i].parent==0) { secmin=HT[i].weight; s2=i; } if(s1>s2) { temp=s1; s1=s2; s2=temp; } code.s1=s1; code.s2=s2; return code; }