来源:网络
#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
;
}
}