适这学期学数据结构,刚刚学了树和二叉树。遂写了哈夫曼编码作业。当然其中还有一部分不是太完善,在这里也就不注释了。
注意:本文的程序是在VS2005下编译的,试过在VC++6下会有错,那是字符串的初始化后不自动为空所产生问题。
下面给出这几个文件
head.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 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定义哈夫曼树的文件什么的。打印哈夫曼树那里还没打印成树形结构
{
unsigned int weight;
char code;
unsigned int parent,lchild,rchild;
}HTNode,*HuffmanTree;
typedef char * *HuffmanCode;
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;
}
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;
}
{
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;
}
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 " 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;
}