适这学期学数据结构,刚刚学了树和二叉树。遂写了哈夫曼编码作业。当然其中还有一部分不是太完善,在这里也就不注释了。
注意:本文的程序是在VS2005下编译的,试过在VC++6下会有错,那是字符串的初始化后不自动为空所产生问题。
下面给出这几个文件
head.h文件操作的函数:
#include
<
stdio.h
>
#include
<
stdlib.h
>
#include
<
conio.h
>
#include
"
stack.h
"
#include
"
hfm.h
"
//
#include"hfm1.h"
void
writefile(
char
*
s,
char
*
fn){
FILE
*
fp ;
int
i
=
0
;
fp
=
fopen(fn,
"
w
"
);
while
(s[i]) {
fputc(s[i], fp);
i
++
;
}
fclose(fp);
}
char
*
readfile(
char
*
fn){
FILE
*
finPtr;
char
str[
10240
];
int
i;
finPtr
=
fopen(fn,
"
r
"
);
//
./src.txt
i
=
readline(finPtr,str,
sizeof
(str));
//
示例中去掉只有回车的行
if
(i
==
1
)
fclose(finPtr);
return
str;
}
int
readline(FILE
*
f,
char
*
str,
int
strlen){
int
ch;
char
*
tmp;
ch
=
0
;
tmp
=
str;
if
(feof(f))
return
-
1
;
while
(
!
feof(f)
&&
ch
!=
0xa
){
ch
=
fgetc(f);
if
(ch
!=
EOF
&&
ch
!=
'
'
){
*
str
=
ch;
str
++
;
}
}
if(*tmp==10 || *tmp=='/0' || *tmp=='/n')/* 如果行首字符等于ellipsis,返回错误代码 1 */
return 0;
else
return 1;
}
stack.h栈的结构文件,但我并没用上栈,不过这个文件里还是有几个函数有用的
#define
FALSE 0
#define
ERROR 0
#define
OK 1
#define
TRUE 1
#define
STACK_INIT_SIZE 30
#define
STACK_ADD 5
typedef
int
Status;
typedef
struct
...
{
char *top;
char *base;
int ssize;
}
Stack;
void
msg(
char
*
c)
...
{
printf("%s ",c);
}
Stack
*
InitS(Stack
*
s)
...
{
s->base=(char *)malloc(STACK_INIT_SIZE*sizeof(char));
if(!s->base) msg("init error");
s->top=s->base;
s->ssize=STACK_INIT_SIZE;
return s;
}
void
DestS( Stack
*
s)
...
{
s->base=NULL;
s->top=s->base;
}
void
Push( Stack
*
s,
char
c)
...
{
if (s->top-s->base >= s->ssize) ...{
s->base = (char *)realloc(s->base ,(s->ssize +STACK_ADD)*sizeof(char));
if(!s->base ) msg("m error ");
s->top = s->base + s->ssize ;
s->ssize += STACK_ADD;
}
*(s->top) = c;
s->top++;
}
Stack
*
Pop( Stack
*
s)
...
{
if (s->top ==s->base ) msg("pop stack error");
s->top--;
return s;
}
char
Gettop( Stack
*
s)
...
{
return *(s->top -1);
}
Status Sempty( Stack
*
s)
...
{
if (s->top ==s->base || s->top==NULL)
return TRUE;
else
return FALSE;
}
hfm.h定义哈夫曼树的文件什么的。打印哈夫曼树那里还没打印成树形结构
typedef struct
{
unsigned int weight;
char code;
unsigned int parent,lchild,rchild;
}HTNode,*HuffmanTree;
typedef char * *HuffmanCode;
void print(HuffmanTree HT,HuffmanCode HC,int n){
int i,j,k;
//printf("/n由于字符多于32且小于64个所以有小于2^6个/n所以每行有32个空格左有32个字符/n");
for(i=1;i<=n;i++) {
// for(j=0;j<32-i;j++)printf(" ");
// for(j=1;j<=i;j++)
// for(i=1;i<=n;i++) {
// if (HC[i]
//printf("%s ",HT[j].code);
// }
printf(" %d %c %d %s/n",i,HT[i].code,HT[i].weight,HC[i]);
}
}
void Select(HuffmanTree HT,int n,int *s1,int *s2){
int i;
(*s1)=(*s2)=0;
for(i=1;i<=n;i++) {
if(HT[i].weight<HT[(*s2)].weight&&HT[i].parent==0&&(*s2)!=0){
if(HT[i].weight<HT[(*s1)].weight) {
(*s2)=(*s1);
(*s1)=i;
} else
(*s2)=i;
}
if(((*s1)==0||(*s2)==0)&&HT[i].parent==0) {
if((*s1)==0)
(*s1)=i;
else
if((*s2)==0) {
if(HT[i].weight<HT[(*s1)].weight) {
(*s2)=(*s1);
(*s1)=i;
} else
(*s2)=i;
}
}
}
if((*s1)>(*s2)) {
i=(*s1);
(*s1)=(*s2);
(*s2)=i;
}
return;
}
void HuffmanCoding(HuffmanTree *HT,HuffmanCode *HC,int *w,char *code,int n) {
int i,m,s1,s2,start,c,f;
char *cd;
if(n<=1) return;
m=2*n-1;
(*HT)=(HuffmanTree)malloc((m+1)*sizeof(HTNode));
for(i=1;i<=n;++i) {
(*HT)[i].code=code[i-1];
(*HT)[i].weight=w[i-1];
(*HT)[i].parent=(*HT)[i].lchild=(*HT)[i].rchild=0;
}
for(;i<=m;++i) {
(*HT)[i].code='0';
(*HT)[i].weight=(*HT)[i].parent=(*HT)[i].lchild=(*HT)[i].rchild=0;
}
for(i=n+1;i<=m;++i)
{
Select(*HT,i-1,&s1,&s2);
(*HT)[s1].parent=i;(*HT)[s2].parent=i;
(*HT)[i].lchild=s1;(*HT)[i].rchild=s2;
(*HT)[i].weight=(*HT)[s1].weight+(*HT)[s2].weight;
}
(*HC)=(HuffmanCode)malloc(n*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].parent;f!=0;c=f,f=(*HT)[f].parent) {
if((*HT)[f].lchild==c)
cd[--start]='0';
else
cd[--start]='1';
}
(*HC)[i]=(char *)malloc((n-start)*sizeof(char));
strcpy((*HC)[i],&cd[start]);
}
msg(">哈夫曼编码初始化完毕");
}
show.h过程 的显示函数就在这里了
char showmenu(int i){
char c[7]={' ',' ',' ',' ',' ',' ',' '};
c[i]='<';
printf("----------------------------------------/n");
printf("| A.构造哈夫曼树%c |/n",c[1]);
printf("| B.对文件进行编码%c |/n",c[2]);
printf("| C.进行译码%c |/n",c[3]);
printf("| D.打印文件%c |/n",c[4]);
printf("| E.打印哈夫曼树%c |/n",c[5]);
printf("| F.退出%c |/n",c[6]);
printf("----------------------------------------/n");
return getch();
}
void printfile(){
char *a;
a=readfile(".//code.txt");
msg(">开始打印文件");
printf("编码部分为:");
while(*a!='/0'){
if(*a=='|')
printf("/n字符串为:");
else
printf("%c",*a);
a++;
}
printf("/n");
msg(">打印文件完毕");
}
void Encoding(HuffmanTree HT,HuffmanCode HC,int n){
char s[100];
char out[1000];
char *temp;
int i=0,j;
msg("请输入要进行编码的字符串:");
scanf("%s",s);
out[0]='/0';
while(s[i]!='/0'){
for(j=1;j<=n;j++) {
if (s[i]==HT[j].code){
temp=HC[j];
strcat(out,temp);
}
}
i++;
}
writefile(out,".//out.txt");
msg(">保存编码后文件完毕");
out[0]='/0';
for(i=1;i<=n;i++){
temp=HC[i];
strcat(out,temp); }
strcat(out,"|");
strcat(out,s);
writefile(out,".//code.txt");
msg(">保存HC完毕");
}
void Uncoding(HuffmanTree HT,HuffmanCode HC,int n){
char *a;
int i=0,j=0,k,l=0;
char out[1000];
char temp[100];
out[0]='/0';
temp[0]='/0';
a=readfile(".//out.txt");
while(*a!='/0'&&*a!=0xa){
temp[j]=*a;
j++;
for(k=1;k<=n;k++) {
if (strcmp(temp,HC[k])==0){
out[l]=HT[k].code;
l++;
while(j>=0){
temp[j]='/0';
j--;
}
j=0;
}
}
a++;
}
out[l]='/0';
msg(">译码完毕");
printf(">译码结果为:%s/n",out);
}
main.c主函数
#include
"
head.h
"
#include
"
show.h
"
main()
...
{
int i=0,n=28;
int w[28]=...{2,4,4,5,2,5,10,5,2,2,5
,10,1,4,3,11,1
,1,3,11,1,4,1,3,1,1,1,2};
char*str1, *str;
char c[28]=...{'a','b','c','d','e','f','g','h','i','j','k'
,'l','m','n','o','p','q'
,'r','s','t','u','v','w','x','y','z',' ','.'};
int j;
char key;
HuffmanTree HT;
HuffmanCode HC;
while(1)...{
if (i<0) i=6;
if (i>6) i=1;
key=showmenu(i);
system("cls");
if (key=='a'||key=='A'||(key==13&&i==1))
HuffmanCoding(&HT,&HC,w,c,n);
if (key=='b'||key=='B'||(key==13&&i==2))
Encoding(HT,HC,n);
if(key=='c'||key=='C'||(key==13&&i==3))
Uncoding(HT,HC,n);
if(key=='d'||key=='D'||(key==13&&i==4))
printfile();
if(key=='e'||key=='E'||(key==13&&i==5))
print(HT,HC,n);
if(key=='f'||key=='F'||(key==13&&i==6))
exit(0);
if(key==72)
i--;
if(key==80)
i++;
if(key==75)
i--;
if(key==77)
i++;
}
return 1;
}