[C] - 哈夫曼算法

来源:网络

 

  
    
#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 ;
}
}

 

 

你可能感兴趣的:(算法)