void hfmtree ( huffnode ht[] ) 是用来建立一课哈夫曼树的,其他函数,视需要可删除
#include<stdio.h>
#include<string.h>
#define maxsize 10000 /*编码函数中,被编译的字符串的最大长度*/
#define max 10000 /*最大字符的个数*/
typedef struct /*定义一个huffnode结点 */
{
char data; /*数据域*/
int weight,parent,left,right;
}huffnode;
typedef struct /*定义一个huffnode结点*/
{
char cd[max]; /*数组cd存放哈夫曼编码*/
int start;
}huffcode;
huffcode hcd[max];
huffnode ht[2*max];
huffnode a[2*max];
void hfmtree ( huffnode ht[] ) /*创建一棵哈夫曼树*/
{
int i,k,x1,x2,n,m1,m2;
n = ht[0].weight;
for ( i=1; i<=2*n-1; i++ )
ht[i].parent = ht[i].left = ht[i].right = 0; /*初始化*/
for ( i=n+1; i<=2*n-1; i++ )
{
m1 = m2 = 200000000;
x1 = x2 = 0;
for ( k=1; k<=i-1; k++ ) /*k为可以进行比较的结点的下标*/
if ( ht[k].parent == 0 ) /*当前结点的父结点不存在时*/
if ( ht[k].weight < m1 ) /*当前结点的权值比最小权值还小时*/
{
m2 = m1;
x2 = x1;
m1 = ht[k].weight;
x1 = k;
}
else if ( ht[k].weight < m2 ) /*当前结点的权值比最小权值大但比第二最小权值小时*/
{
m2 = ht[k].weight;
x2 = k;
}
ht[x1].parent = ht[x2].parent = i;
ht[i].weight = ht[x1].weight + ht[x2].weight;
ht[i].left = x1;
ht[i].right = x2;
}
}
void output ( huffnode ht[] ) /*输出哈夫曼编码*/
{
huffcode d;
int i,n,c,f,k,x;
n = ht[0].weight;
for ( i=1; i<=n; i++ )
{
d.start = n+1;/*d.start为栈项*/
c = i; /*c存放当前结点*/
f = ht[i].parent;/*f存放当前结点的父结点*/
while ( f != 0 )
{
if ( ht[f].left == c ) /*若当前结点在其父结点的左边时*/
d.cd[--d.start] = '0';
else
d.cd[--d.start] = '1'; /*当前结点在其父结点的右边时*/
c = f; /*当前结点的父结点赋予c*/
f = ht[f].parent; /*c的父结点赋予f*/
}
hcd[i] = d; /*将当前结点的哈夫曼编码赋予hcd[i]数组*/
}
printf ( "哈夫曼编码: \n" );
for ( i=1; i<=n; i++ ) /*输出各个结点的哈夫曼编码*/
{
if ( ht[i].data == ' ' )
printf ( "' ' " );
else
printf ( "%c ",ht[i].data );
x = hcd[i].start;
for ( k=x; k<=n; k++ ) /*通过栈输出哈夫曼编码*/
printf ( "%c",hcd[i].cd[k] );
printf ( "\n" );
}
printf ( "* * * * * * * * * * * * * * * * * * * * \n\n" );
}
void coding ( huffcode hcd[],huffnode ht[] ) /*编码函数,给定一个字符串,输出其对应的哈夫曼编码*/
{
int i,j,n,m,k,x;
char in[maxsize],out[2*maxsize];/*in存放需编译的字符串,out存放编译后的代码*/
m = 0;
printf ( "请输入一串字符串:" );
getchar();
gets(in);
n = strlen(in);
for ( i=0; i<n; i++ )
{
for ( j=1; j<=ht[0].weight; j++ ) /*ht[0].weight 存放的是带权结点的个数*/
if ( in[i] == ht[j].data ) /*若输入字符和一个带权结点相同*/
{
x = hcd[j].start;
for ( k=x; k<=ht[0].weight; k++ )
out[m++] = hcd[j].cd[k];
}
}
printf ( "编码结果是:\n" );
for ( i=0; i<m; i++ )
printf ( "%c",out[i] );
printf ( "\n" );
}
void decoding ( huffcode hcd[],huffnode ht[] )/*译码函数,输入一个代码流,输出其对应的字符*/
{
int i,j,n,k,x,m,w;
char in[maxsize*2],out[maxsize];/*in数组存放代码流,out数组存放对应数组*/
printf ( "请输入由0和1组成的字符串:\n" );
scanf ( "%s",in );
n = strlen(in);
i = m = 0; /*i为in数组的下标,m为out数组的下标*/
while ( i<n )
{
for ( j=1; j<=ht[0].weight; j++ )/*ht[0].weight为带权结点的个数*/
{
x = hcd[j].start;
for ( k=x,w=i; k<=ht[0].weight; k++,w++) /*k为hcd[j].cd[]的下标*/
if ( in[w] != hcd[j].cd[k] )
break;
if ( k > ht[0].weight )
{
out[m++] = ht[j].data;
break;
}
}
i = w;
}
printf ( "解码结果是:\n" );
for ( i=0; i<m; i++ ) /*输出结果*/
printf ( "%c",out[i] );
printf ( "\n" );
}
int main()
{
int select,index,i,k,len;
char str[10000];
printf ( "请输入一篇文章以便编码:\n" );
gets (str);
for ( index=0; index<=200; index++ ){//初始化
a[index].data = '#';
a[index].weight = 0;
}
len = strlen(str);
k = 27;
for ( index=0; index<len; index++ ){//赋值
if ( str[index]>='A' && str[index]<='Z' ){
a[str[index]-'A'+1].data = str[index];
a[str[index]-'A'+1].weight++;
}
else{
a[k].data = str[index];
a[k].weight++;
k++;
}
}
k = 1;
for ( i=0; i<200; i++ )
if ( a[i].data != '#' ){
ht[k].data = a[i].data;
ht[k].weight = a[i].weight;
k++;
}
ht[0].weight = k-1;
hfmtree (ht); //建树
output (ht);
do
{
printf ( "*************\n" );
printf ( "0.退出\n" );
printf ( "1.编码\n" );
printf ( "2.解码\n" );
printf ( "3.遍历\n" );
printf ( "请输入你的选择:" );
scanf ( "%d",&select );
if ( select == 0 )
{
printf ( "感谢使用!\n" );
return 0;
}
if ( select == 1 )
coding ( hcd,ht );
else if ( select == 2 )
decoding ( hcd,ht );
}while(1);
return 0;
}
追问编译通不过,是哪儿出了问题呢?