一.题目要求
单词的词频统计
(1)从文件中读出一篇英文文章,将不同的单词存入堆中,建立相应的索引表,索引表确定各单词在堆中存储的位置及出现的次数。(索引表的数据类型要求采用第4章课件中最后的应用举例的方式)
(2)按出现的频率递减的次序输出结果并存入文件。
(3)选做:查找、插入、删除等
二.算法设计
1.按照题目的要求我把整个程序分为以下8个部分
A.从文件中读入一片英语文章
B.将不同的单词存入到堆中
C.建立相应的索引表
D.索引表确定各单词在堆中存储的位置及出现的次数
E.按照出现的递减的频率排序并输出结果存入文件
F.给定单词查找堆中的单词
G.在堆中删除单词
H.在堆中插入单词
2.主要算法设计思想
思想大概:按照小红老师学习通里面的视频,我先进行了对主要功能实现(索引表),首先先创建一个很大的堆(数组空间),再按照结构体的创建建立索引表和索引项,索引表中有指向索引项里面最后一个单词的last指针,有指向堆的第一个可以利用的空间地址的free指针以及其他的,先按照char *string[100]的格式随便赋值几个单词,初始化索引表和索引项,把每一个单词初始为一个既包含单词有包含单词长度的结构体形式,把单词依次读入索引表和索引项里面,这就实现基本功能,在此基础上面,建立Judgement_repetition(判断重复)函数,对每一个单词读入进行判断在索引项里面是否有重复单词,如果有的话就该索引项频度加加,没有的话就读入到索引项里面存储在索引表里面,然后就是文本文件的读入,读入文本文件后,通过小红老师提示的分单词的功能,把文本文件里面每一个单词都存储在一个word字符型里面,再把word导入前面提到的char *string[100]数组里面,功能就完全对接上了,接下来就是按照每个单词的频度对单词进行排序,在这里我使用了C++里面的sort函数,建立一个cmp函数对结构体里面的频度进行排序,排序完成之后就可以输出了,查找单词的功能就很简单了,进入索引项,按照首地址来对比就行,增加单词在查找基础上面,如果查找失败就增加,查找成功就频度加加,删除单词功能也在查找的基础上面,如果查找成功就直接删除,索引项里面的每个成员向前面移动一个last指针减减就行,存入文件功能就是建立一个全局字符型数组,把索引项里面对应首地址的单词存入再把频度存入就行,把这个数组导入文件操作就行
三.程序源代码
PS:输入文件为:3.input.txt
输出文件为:3.output.txt
(可能有些地方还有问题,大家请谅解一下,我自己的编程水平也很一般啦)
(功能都能实现,我自己也都测试了好多遍,应该问题不大)
(有需要的拿去用吧!狗头保命)
#include<iostream>
#include<cstdio>
#include <stdlib.h>
#include<algorithm>
using namespace std;
#define worldmaxlen 40 //最大单词长度
#define maxsize 10000 //最大范围
#define maxworldnum 100 //最大单词数量
#define bufsize 1000 //输入文件一行最多单词
int counter=0; //记录文本单词的数目
int record=0; //记录所有单词数
typedef struct{
//建立能存储单词和长度的结构体
char data[worldmaxlen];
int len;
}sqstring;
typedef struct {
//建立索引项
int firstadd;
int len;
int frn;
}indextem;
typedef struct{
//建立索引表
char space[maxsize];
indextem item[maxworldnum];
int free; //用来表示这个space空间的第一个能利用的存储空间
int last; //用来表示这个索引项最后一个存储的位置
}indexlist;
int cmp(indextem E1,indextem E2){
//sort对结构体的排序
return E1.frn>E2.frn;
}
void initindexlist(indexlist *&list){
//初始索引项
list=(indexlist*)malloc(sizeof(indexlist));
list->free=0;
list->last=-1;
}
void creatstr(sqstring &str,char *sp){
//将字符串中的单词导入顺序串中
str.len=0; //因为能增加一个str.len的值
int i=0;
while((*sp)!='\0'){
str.data[i]=*sp;
sp++;
i++;
}
str.len=i;
str.data[i+1]='#';//用作结束标记
}
void initstr(sqstring &str){
//初始字符串,全部以#结尾方便操作
for(int i=0;i<worldmaxlen;i++)
{
str.data[i]='#';
}
str.len=0;
}
int Judgement_repetition(sqstring str,indexlist *&list)//判断重复
{
int ii;
for(ii=0;ii<=list->last;ii++){
if(str.len==list->item[ii].len){
int j=0;
int k=list->item[ii].firstadd;
int mark=0,temp=0,count1=0;
while(str.data[j]!='#'&&char(list->space[k])!=' '&&str.data[j]==char(list->space[k])){
//cout<<"字母为:"<<str.data[j]<<" "<<list->space[k]<<endl;
if(str.data[j]==char(list->space[k]))
mark=1;
if(str.data[j]!=char(list->space[k])){
mark=0;
}
//cout<<"Mark标记为"<<mark<<endl;
j++;list->item[ii].firstadd++;
k=list->item[ii].firstadd;
temp++;count1++;
//cout<<"接下来字母为:"<<str.data[j]<<" "<<list->space[k]<<endl;
if(count1!=str.len){
mark=0;
}else{
mark=1;
}
}
for(int i=0;i<temp;i++){
list->item