#include<stdio.h> |
#include<malloc.h> |
#include<conio.h> |
#include<stdlib.h> |
#include<string.h> |
/*声明两种链表结构----start*/ |
struct node_a { /*链表1-----作用:用来统计文件中字符的个数和种类(通过count)*/ |
char data; |
int count; |
struct node_a *next; |
}; |
typedef struct node_a node,*list; |
list head=NULL; |
struct nodeb { /*链表2-----作用:用来建立用相应的编码代替字符的新文件*/ |
char data; |
struct nodeb *next; |
}; |
typedef struct nodeb node_b,*list_b; /*jiang bianma xieru wenjian*/ |
list_b head_b=NULL; |
/*声明两种链表结构----end*/ |
/*哈夫曼算法种相关的3种结构的声明-----start*/ |
struct forest { |
float weight; |
int root; |
}; |
struct alphabet { |
char symbol; |
float probability; |
int leaf; |
char *bianma; |
}; |
struct tree { |
int lchild; |
int rchild; |
int parent; |
}; |
typedef struct tree *tree_ptr,tree_node; |
typedef struct forest *forest_ptr,forest_node; |
typedef struct alphabet *alphabet_ptr,alphabet_node; |
tree_ptr tree1; |
forest_ptr forest1; |
alphabet_ptr alphabet1; |
int lasttree,lastnode; |
int least,second; |
/*哈夫曼算法种相关的3种结构的声明-----end*/ |
/**************stack difination start****************/ |
struct stacknode { |
char *bian_ma; |
struct stacknode *next; |
}; |
typedef struct stacknode stack_node; |
typedef stack_node *link; |
link top=NULL; |
void push ( char *item ) { |
link p; |
if ( top!=NULL ) { |
p= ( link ) malloc ( sizeof ( stack_node ) ); |
if ( p==NULL ) { |
printf ( "Memory allocation error!" ); |
return ; |
} |
p->bian_ma=item; |
p->next=top; |
top=p; |
} else { |
top= ( link ) malloc ( sizeof ( stack_node ) ); |
if ( !top ) { |
printf ( "Memory allocation error!" ); |
return ; |
} |
top->bian_ma=item; |
top->next=NULL; |
} |
} |
void pop ( void ) { |
link p; |
p=top; |
top=top->next; |
free ( p ); |
} |
void makenull ( void ) { |
while ( top!=NULL ) |
pop(); |
} |
int empty() { |
if ( top==NULL ) |
return 1; |
else |
return 0; |
} |
char * tops ( void ) { |
return ( top->bian_ma ); |
} |
void display_stack ( link s ) { /*显示栈重的内容*/ |
link ptr; |
ptr=s; |
while ( ptr!=NULL ) { |
printf ( "%s" ,ptr->bian_ma ); |
ptr=ptr->next; |
} |
} |
/***************************stack__difination is end************************/ |
void display ( list h ) { /*显示链表1*/ |
list ptr; |
int i=1; |
ptr=h->next; |
while ( ptr!=NULL ) { |
printf ( "%d,%c,%d\n" ,i,ptr->data,ptr->count ); |
i++; |
ptr=ptr->next; |
} |
} |
void display_b ( list_b h ) { /*显示链表2*/ |
list_b ptr; |
int i=1; |
ptr=h->next; |
while ( ptr!=NULL ) { |
printf ( "%d,%c\n" ,i,ptr->data ); |
i++; |
ptr=ptr->next; |
} |
} |
void insert ( char item ) { /*用于插入元素以建立链表1*/ |
list temp,ptr; |
int flag; |
ptr=head->next; |
if ( ptr==NULL ) { |
head->next= ( list ) malloc ( sizeof ( node ) ); |
head->next->data=item; |
head->next->count=1; |
head->next->next=NULL; |
} else { |
while ( ptr!=NULL ) { |
if ( ptr->data==item ) { |
ptr->count=ptr->count+1; |
flag=1; |
} |
ptr=ptr->next; |
} |
ptr=head; |
if ( flag==1 ) |
return ; |
else { |
temp=ptr->next; |
ptr->next= ( list ) malloc ( sizeof ( node ) ); |
ptr->next->data=item; |
ptr->next->count=1; |
ptr->next->next=temp; |
} |
} |
} |
void insert_b ( char item ) { /*插入元素以建立链表2*/ |
list_b ptr_b, temp_b; |
ptr_b=head_b; |
if ( ptr_b->next==NULL ) { |
head_b->next= ( list_b ) malloc ( sizeof ( node_b ) ); |
head_b->next->data=item; |
head_b->next->next=NULL; |
} else { |
while ( ptr_b->next!=NULL ) { |
ptr_b=ptr_b->next; |
} |
ptr_b->next= ( list_b ) malloc ( sizeof ( node_b ) ); |
ptr_b->next->data=item; |
ptr_b->next->next=NULL; |
} |
} |
void search ( void ) { /*搜索文件并将文件中的数据分别存入作用不同的链表中*/ |
FILE *fp; |
list ptr; |
char ch; |
if ( ( fp= fopen ( "test.txt" , "r" ) ) ==NULL ) |
printf ( "Reading error!\n" ); |
while ( ! feof ( fp ) ) { |
ch= getc ( fp ); |
if ( ferror ( fp ) ) { |
printf ( "error!\n" ); |
break ; |
} |
if ( ch==EOF ) |
break ; |
insert ( ch ); /*插入元素进链表1*/ |
insert_b ( ch ); /*插入元素进链表2*/ |
} |
printf ( "\n" ); |
fclose ( fp ); |
} |
void display_struct ( int n ) { /*显示哈夫曼算法中的3个结构树组 */ |
int i=0; |
printf ( "\n\n=======================================\n\n" ); |
printf ( "FOREST_STRUCT_ARRY :\n\n\n" ); |
for ( i=0; i<=n; i++ ) { |
printf ( "%f,%d\n" ,forest1[i].weight,forest1[i].root ); |
} |
getch(); |
printf ( "\n\nALPHABET_STRUCT_ARRY :\n\n\n" ); |
for ( i=0; i<=n; i++ ) { |
printf ( "%f,%d,%c\n" ,alphabet1[i].probability,alphabet1[i].leaf,alphabet1[i].symbol ); |
} |
getch(); |
printf ( "\n\nTREE_STRUCT_ARRY :\n\n\n" ); |
for ( i=0; i<=2*n-1; i++ ) |
printf ( "%d,%d,%d\n" ,tree1[i].lchild,tree1[i].rchild,tree1[i].parent ); |
printf ( "\n\n======================================\n\n" ); |
getch(); |
} |
int init_struct ( void ) { /*初始化哈夫曼算法中3种结构数组*/ |
list ptr; |
float count=.0; |
int i=1,n=0; |
ptr=head->next; |
while ( ptr!=NULL ) { |
count=ptr->count+count; |
n++; |
ptr=ptr->next; |
} |
ptr=head->next; |
forest1= ( forest_ptr ) malloc ( sizeof ( forest_node ) *n+ sizeof ( forest_node ) ); |
alphabet1= ( alphabet_ptr ) malloc ( sizeof ( alphabet_node ) *n+ sizeof ( alphabet_node ) ); |
tree1= ( tree_ptr ) malloc ( sizeof ( tree_node ) *n*2- sizeof ( tree_node ) ); |
forest1[0].weight=alphabet1[0].probability=0.0; |
forest1[0].root=alphabet1[0].leaf=0; |
alphabet1[0].symbol= '0' ; |
while ( ptr!=NULL ) { |
forest1[i].weight=alphabet1[i].probability=ptr->count/count; |
forest1[i].root=alphabet1[i].leaf=i; |
alphabet1[i].symbol=ptr->data; |
i++; |
ptr=ptr->next; |
} |
for ( i=0; i<=2*n-1; i++ ) { |
tree1[i].lchild=0; |
tree1[i].rchild=0; |
tree1[i].parent=0; |
} |
return n; |
} |
void creat ( void ) { /*创建正文文件test.txt*/ |
FILE *fp,*out; |
char ch; |
if ( ( fp= fopen ( "test.txt" , "r++" ) ) ==NULL ) |
printf ( "Creat error!\n" ); |
printf ( "Input the data:\n" ); |
ch=getch(); |
putch ( ch ); |
while ( ch!= '#' ) { |
putc ( ch,fp ); |
ch=getch(); |
putch ( ch ); |
} |
fclose ( fp ); |
} |
void creat_bianma ( int number ) { /*根据哈夫曼算法建立文件中各种字符对应的编码*/ |
int i,j,n; |
int p; |
char *bm= malloc ( sizeof ( char ) *number ); |
for ( n=1; n<=number; n++ ) { |
j=i=n; |
makenull(); |
p=tree1[i].parent; |
while ( tree1[p].parent!=0 ) { |
if ( tree1[p].lchild==i ) |
push ( "0" ); |
else |
push ( "1" ); |
i=p; |
p=tree1[p].parent; |
} |
if ( tree1[p].lchild==i ) |
push ( "0" ); |
else |
push ( "1" ); |
strcpy ( bm, " " ); /*目的:使创建编码文件中的各编码中间存在间隔*/ |
while ( !empty() ) { |
strcat ( bm,tops() ); |
pop(); |
} |
alphabet1[j].bianma= malloc ( sizeof ( char ) *number ); |
strcpy ( alphabet1[j].bianma,bm ); |
printf ( "\n%c:%s" ,alphabet1[j].symbol,alphabet1[j].bianma ); /*打印出相应的编码*/ |
getch(); |
} |
} |
void write_new_file ( int number ) { /*根据相应的编码重新建立编码文件*/ |
FILE *fp; |
list_b ptr; |
int i; |
char *ch= malloc ( sizeof ( char ) *number ); |
ptr=head_b->next; |
if ( ( fp= fopen ( "bianma.txt" , "w" ) ) ==NULL ) |
printf ( "Write in a new file error!" ); |
else { |
while ( ptr!=NULL ) { |
for ( i=1; i<=number; i++ ) { |
if ( ptr->data==alphabet1[i].symbol ) { |
strcpy ( ch,alphabet1[i].bianma ); |
fputs ( ch,fp ); |
} |
} |
ptr=ptr->next; |
} |
} |
fclose ( fp ); |
} |
void main ( void ) { |
int i,num; |
char ch; |
void huffman ( void ); |
void lightones(); |
head= ( list ) malloc ( sizeof ( node ) ); |
head->next=NULL; |
head->data= '\0' ; |
head->count=0; |
head_b= ( list_b ) malloc ( sizeof ( node_b ) ); |
head_b->data= '\0' ; |
head_b->next=NULL; |
do { |
system ( "cls" ); |
creat(); |
search(); |
printf ( "\nlianbiao1:\n" ); |
display ( head ); /*显示链表1*/ |
getch(); |
printf ( "\nlianbiao2:\n" ); |
display_b ( head_b ); |
getch(); |
num=init_struct(); |
printf ( "\n" ); |
printf ( "The 3 init_struct of huffman?\n" ); |
display_struct ( num ); /*显示初始化的哈夫曼书的相关3个结构数组*/ |
lastnode=num; |
lasttree=num; |
huffman(); |
printf ( "Now the 3 struct through huffman shuanfa\n" ); |
display_struct ( num ); /*显示哈夫曼树中相关的3种结构(经过哈夫曼算法处理)*/ |
printf ( "\nThe bian_ma is:\n" ); |
creat_bianma ( num ); |
write_new_file ( num ); |
printf ( "\nDo you want to re_try(y/n)?" ); |
ch= getchar (); |
} while ( ch== 'y' ); |
} |
/*哈夫曼算法-----defination_start*/ |
void lightones ( void ) { |
int i; |
if ( forest1[1].weight<=forest1[2].weight ) { |
least=1; |
second=2; |
} else { |
least=2; |
second=1; |
} |
for ( i=3; i<=lasttree; i++ ) |
if ( forest1[i].weight<forest1[least].weight ) { |
second=least; |
least=i; |
} else if ( forest1[i].weight<forest1[second].weight ) |
second=i; |
} |
int creat_tree ( int lefttree, int righttree ) { |
lastnode=lastnode+1; |
tree1[lastnode].lchild=forest1[lefttree].root; |
tree1[lastnode].rchild=forest1[righttree].root; |
tree1[lastnode].parent=0; |
tree1[forest1[lefttree].root].parent=lastnode; |
tree1[forest1[righttree].root].parent=lastnode; |
return ( lastnode ); |
} |
void huffman ( void ) { |
int i,j; |
int newroot; |
while ( lasttree>1 ) { |
lightones(); |
i=least; |
j=second; |
newroot=creat_tree ( i,j ); |
forest1[i].weight=forest1[i].weight+forest1[j].weight; |
forest1[i].root=newroot; |
forest1[j]=forest1[lasttree]; |
lasttree=lasttree-1; |
} |
} |