求大神看看这个程序吧,这是一个赫夫曼编码题,将根据输入字母个数的多少作为权值将字母进行编码,当输入的字母个数很多时程序在for循环里面就出错了
#include <stdio.h>#include <stdlib.h>
#include <string.h>
#define M 200
typedef struct {
char c;
int count;
int parent,lchild,rchild;
char Hcode[6];
}HTNode, *HuffmanTree;
typedef char * * HuffmanCode;
HTNode L[26];
const int N=sizeof(HTNode);
HuffmanTree HT=NULL;
HuffmanCode HC=NULL;
void main() {
int CountLetter(char str[]);
void HuffmanCoding(HuffmanTree HT, HuffmanCode HC, int n);
void Coding(char str[],char *p);
void Translate(char code[], char *p,int n);
FILE *fp;
int i,n;//n为短文中出现的不同英文字母的个数
char str1[M],str2[M],str3[M];
char code1[26*M]="\0",code2[26*M]="\0";//此处必须让code初始化‘\0’,否则会出现错误。
for(i=0; i<26; i++)
L[i].count=0;
printf("Please input centenses : \n");
gets(str1);
if((fp=fopen("a","w"))==NULL) {
printf("can't open file\n");
exit(0);
}//用只写入的方式打开“a”文件
fputs(str1,fp);//向文件“a”中写入该短文
fclose(fp);//打开文件后要将其关闭,否则会出现泄露
if((fp=fopen("a","r"))==NULL) {
printf("Error!\n");
exit(0);
}//用只读的方式打开文件“a”
fgets(str2,M,fp);//从fp指向的文件中读取字符串并将其放入字符串str中
fclose(fp);
//puts(str2);
n=CountLetter(str2);
HuffmanCoding(HT, HC, n);
Coding(str2,code1);
if((fp=fopen("b","w"))==NULL) {
printf("can't open file\n");
exit(0);
}//打开文件b并向其写入已编码的短文
fputs(code1,fp);
fclose(fp);
if((fp=fopen("b","r"))==NULL) {
printf("ERROR!\n");
exit(0);
}
fgets(code2,26*M,fp);
fclose(fp);
// puts(code2);
// Translate(code2,str3,n);
// puts(str3);
}
int CountLetter(char str[]) {
int i=0,j,flag;//如果数组L中出现了要查找的字母,则flag=1,否则flag=0
for(i=0; str[i]!='\0'; i++) {//检查str[i]是否已在数组L中出现,若出现则将其出现次数加一,若没有出现将其放入L中并让其出现次数加一
flag=0;
if(str[i]!=' ' && str[i]!=',') {
for(j=0; flag==0 && L[j].count!=0; j++) {
if(L[j].c==str[i] || L[j].c==str[i]+32) {
L[j].count++;
flag=1;
}
}
if(flag==0) {
if(str[i]>64 && str[i]<91)
L[j].c=str[i]+32;
else
L[j].c=str[i];
L[j].count++;
}
}
}
for(i=0; L[i].count!=0 ;i++)
printf("%c %d\n",L[i].c,L[i].count);
printf("总的出现字母的个数为%d\n",i);
return i;
}
void HuffmanCoding(HuffmanTree HT, HuffmanCode HC, int n) {//构建赫夫曼树HT,并求出n个字符的赫夫曼编码
int i,j,k,m,start,c,f;//m为赫夫曼树总的结点个数,start是编码个数,c为结点,f为c的父亲
int min;//min为最小权值
int s1,s2;//s1为权值最小结点在HT中的存储位置,s2为权值次小结点在HT中的位置
char *cd;
HuffmanTree p;
if(n<=1) return ;
m=2*n-1;
HT=(HuffmanTree) malloc((m+1) * sizeof(HTNode));
for(i=1; i<=n; ++i) {//切记p的值变化
HT[i*N].c=L[i-1].c;
HT[i*N].count=L[i-1].count;
HT[i*N].parent=0;
HT[i*N].lchild=0;
HT[i*N].rchild=0;
// p=HT+i*N;
// p->c=L[i-1].c;
// p->count=L[i-1].count;
// p->parent=0;
// p->lchild=0;
// p->rchild=0;
// p->Hcode;
}
for(; i<=m; ++i) {
// printf("p.");
// p=HT+i*N;
// p->c=' ';
// p->count=0;
// p->lchild=0;
// p->parent=0;
// p->rchild=0;
HT[i*N].c=' ';
HT[i*N].count=0;
HT[i*N].parent=0;
HT[i*N].lchild=0;
HT[i*N].rchild=0;
}
printf("wwwwwww");
for(i=n+1; i<=m; ++i) {//建赫夫曼树
//Select(HT,i-1,s1,s2);
for(k=1; HT[k*N].parent!=0 && k<=i-1; k++) ;
min=HT[k*N].count;
s1=k;
for(j=1; j<i; j++) {
if(HT[j*N].count < min && HT[j*N].parent==0) {
min=HT[j*N].count;
s1=j;
}
}
for(k=1; HT[k*N].parent!=0 || k==s1; k++) ;
min=HT[k*N].count;
s2=k;
for(j=1; j<i; j++) {
if(HT[j*N].count < min && HT[j*N].parent==0 && j!=s1) {
min=HT[j*N].count;
s2=j;
}
}//目的找到HT中权值较小的两个结点
HT[s1*N].parent=i;
HT[s2*N].parent=i;
HT[i*N].lchild=s1;
HT[i*N].rchild=s2;
HT[i*N].count=HT[s1*N].count+HT[s2*N].count;
}
//从叶子到根逆向求每个字符的赫夫曼编码
//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*N].parent; f!=0; c=f, f=HT[f*N].parent) {
if(HT[f*N].lchild==c)
cd[--start]='0';
else
cd[--start]='1';
}
strcpy(L[i-1].Hcode,&cd[start]);
}
for(i=1; i<=n; i++)
printf("%c %s\n",L[i-1].c,L[i-1].Hcode);
free (cd);
}
void Coding(char str[],char *p) {
int i,j;
for(i=0; str[i]!='\0'; i++) {
if(str[i]==' ')
strcat(p," ");
if(str[i]==',')
strcat(p,",");
if(str[i]!=' ' && str[i]!=',') {
for(j=1; str[i]!=L[j-1].c && str[i]!=L[j-1].c-32; j++) ;
strcat(p,L[j-1].Hcode);//将每个字母的编码连接在一起
}
}
printf("%s",p);
}