一、实验内容
- 对于一篇给定的英文文章,分别利用线性表和二叉排序树来实现单词频率的统计,实现低频词的过滤,并比较两种方法的效率。具体要求如下:
二、实验要求
- 读取英文文章文件(Infile.txt),识别其中的单词。
- 分别利用线性表和二叉排序树构建单词的存储结构。当识别出一个单词后,若线性表或者二叉排序树中没有该单词,则在适当的位置上添加该单词;若该单词已经被识别,则增加其出现的频率。
- 统计结束后,删除出现频率低于五次的单词,并显示该单词和其出现频率。
- 其余单词及其出现频率按照从高到低的次序输出到文件中(Outfile.txt),同时输出用两种方法完成该工作所用的时间。
- 计算查找表的ASL值,分析比较两种方法的效率。
- 系统运行后主菜单如下:
-
当选择1后进入以下界面:
-
其中选择2时显示利用线性表来实现所有功能所用的时间。
当在主菜单选择2二叉排序树后,进入的界面与上图类同。
三、实现提示:
1、在统计的过程中,分词时可以利用空格或者标点符号作为划分单词依据,文章中默认只包含英文单词和标点符号。
2、对单词进行排序时,是按照字母序进行的,每个结点还应包含该单词出现的频率。
3、存储结构的定义
- 二叉排序树的存储表示
-
typedef struct BSTNode{
string WordName; //单词名称
int count; //单词出现频率
struct BSTNode *next;
} BSTNode, *BSTree;
4、实现过程可参见教材上线性表和二叉排序树的相关算法。
四、实验方案及其论证
语言:C
运行环境:C-Free5.0
可行性分析:建立单链表存储InFile.txt英语文章单词及频率,建立二叉排序树存储InFile.txt英语文章单词和频率,分别实现单词统计,删除频率低的单词,输出其余单词,并计算ASL值。
五、伪代码
线性表实现伪代码
double LLNode(int M)
{// 统计文章 InFile.txt 中的单词
printf("**************************************\n");
FILE *fp;
char ch,array[1000][20];int i=0,j=0,k=0,jj;
fp=fopen("InFile.txt","r");// 打开文件
if (fp==NULL){ printf("cannot open file\n");exit(0);}
LNode *L,*P,*Q;// 定义结构指针
L=Q=(LNode *)malloc(sizeof(LNode));L->next=NULL;
while((ch=fgetc(fp))!=EOF)
{
if(ch=='-'||ch=='\'')continue;//
else if(ch<65||(ch>90&&ch<97)||ch>122)// 单词
{
if(j==0)continue;// 输入的是空格或数字或符号
if(L->next){// 第二个以后的单词进入单链表
P=(LNode *)malloc(sizeof(LNode));array[i][j]=0;
for(jj=0;array[i][jj]!='\0';jj++)
P->Wordname[jj]=array[i][jj];
P->Wordname[jj]='\0';P->count=1;P->next=NULL;
while(1)
{
if(strcmp(Q->next->Wordname,P->Wordname)!=0) Q=Q->next;
else {Q->next->count++;break;}// 有相同的单词6
if(!Q->next){Q->next=P;break;}// 没有相同的单词
}if(M==1)printf(" %s",array[i]);
}
else {// 第一个单词 ,头结点无数据
P=(LNode *)malloc(sizeof(LNode));array[i][j]=0;
for(jj=0;array[i][jj]!='\0';jj++)
P->Wordname[jj]=array[i][jj];
P->Wordname[jj]='\0';P->count=1;P->next=NULL;L->next=P;
if(M==1)printf("%s",array[i]);
}
i++;j=0;Q=L;//Q 指向头结点
}
else if(ch>64&&ch<91)array[i][j++]=ch+32;// 大写字母
else array[i][j++]=ch;
}
if(M==1)printf("\n 单词数: %d\n",i);
if(M==1||M==2||M==3)k=wordscount(Q,M);
if(M==1||M==2||M==4||M==5)L=deletelow(L,M);
if(M==1||M==2||M==5)k=tjsyword(L,M);
return (k+1)/2.0;
}
二叉排序树实现伪代码
int STBNode(int m)
{
printf("**************************************\n");
FILE *fp;
char ch[40],cc[20];int i=0,j=0,l=1;double kk=1;
BSTree *B,*SS,*T,*N,*M;
T=B=(BSTree* )malloc(sizeof(BSTree));
fp=fopen("InFile.txt","r");// 打开文件
if (fp==NULL){ printf("cannot open file\n");exit(0);}
fscanf(fp,"%s",cc);// 取出根节点
for(i=0;cc[i]!='\0';i++)
if(cc[i]>64&&cc[i]<91)cc[i]=cc[i]+32;
strcpy(B->wordname,cc);
B->count=1;B->lchild=B->rchild=NULL;
if(m==1)printf("%s ",B->wordname);
while(fscanf(fp,"%s",ch)!=EOF)
{
j=0;
for(i=0;ch[i]!='\0';i++)
{// 单词处理
if(ch[i]=='-'||ch[i]=='\'')continue;
if(ch[i]>64&&ch[i]<91)cc[j++]=ch[i]+32;
else if(ch[i]>96&&ch[i]<123)cc[j++]=ch[i];
else {// 连续多个单词在一起时
cc[j]='\0';j=0;
if(cc[0]!='\0'){
SS=(BSTree* )malloc(sizeof(BSTree));
SS->lchild=SS->rchild=NULL;SS->count=1;
strcpy(SS->wordname,cc);
if(m==1)printf("%s ",cc);l++;
N=seachbstree(B,cc);// 到树中比较,返回访问树的最后一个节点;
if(N==NULL)continue;
if(!N->lchild||!N->rchild)// 插入到树中
{
if(strcmp(N->wordname,SS->wordname)>0){N->lchild=SS;kk++;}
else
if(strcmp(N->wordname,SS->wordname)<0){N->rchild=SS;kk++;}
}B=T;
}
}
}cc[j]='\0';
if(cc[0]!='\0')
{// 读入的是单个单词时
SS=(BSTree* )malloc(sizeof(BSTree));
SS->lchild=SS->rchild=NULL;SS->count=1;
N=seachbstree(B,cc);
if(m==1)printf("%s ",cc);l++;
if(N==NULL)continue;
strcpy(SS->wordname,cc);
if(!N->lchild||!N->rchild)// 插入到树中
{
if(strcmp(N->wordname,SS->wordname)>0){N->lchild=SS;kk++;}
else if(strcmp(N->wordname,SS->wordname)<0){N->rchild=SS;kk++;}
}
B=T;
}
}
if(m==1)printf("\n 单词数: %d",l);
M=(BSTree* )malloc(sizeof(BSTree));
if(m==3){asl=LevelOrderTraverse(T)/kk;
printf(" 单词种数: %d\n",(int)kk);}
if(m==4||m==5||m==2)
{
deleteLOW(M,T,m);
if(m==5||m==2)
{
FILE *fp=fopen("OutFile1.txt","w");
clock_t start=clock();
InOrderTraverse(L,m,fp);
clock_t end=clock();
if(m==5){printf(" 高频词个数: %d\n",(int)gp);
asl=LevelOrderTraverse(L)/gp;gp=0;}
printf("\ntime:%.3fs\n",double(end-start)/CLOCKS_PER_SEC);
fprintf(fp,"\ntime:%.3fs\n",double(end-start)/CLOCKS_PER_SEC);
fclose(fp);
}
}
}