一.实验内容
-
对于一篇给定的英文文章,利用线性表和二叉排序树来实现单词频率的统计,实现低频词的过滤,并比较两种方法的效率。具体要求如下:
-
读取英文文章文件(Infile.txt),识别其中的单词。
-
分别利用线性表和二叉排序树构建单词的存储结构。当识别出一个单词后,若线性表或者二叉排序树中没有该单词,则在适当的位置上添加该单词;若该单词已经被识别,则增加其出现的频率。
-
统计结束后,删除出现频率低于五次的单词,并显示该单词和其出现频率。
-
其余单词及其出现频率按照从高到低的次序输出到文件中(Outfile.txt),同时输出用两种方法完成该工作所用的时间。
-
计算查找表的ASL值,分析比较两种方法的效率。
-
系统运行后主菜单如下:
当选择1后进入以下界面:
其中选择2时显示利用线性表来实现所有功能所用的时间。
当在主菜单选择2二叉排序树后,进入的界面与上图类同。
二.实验提示
1、在统计的过程中,分词时可以利用空格或者标点符号作为划分单词依据,文章中默认只包含英文单词和标点符号。
2、对单词进行排序时,是按照字母序进行的,每个结点还应包含该单词出现的频率。
3、存储结构的定义
二叉排序树的存储表示
typedef struct BSTNode{
string WordName; //单词名称
int count; //单词出现频率
struct BSTNode *next;
} BSTNode, *BSTree;
4、实现过程可参见教材上线性表和二叉排序树的相关算法。
三.实验代码
#include<iostream>
#include<vector>
#include<string>
#include<fstream>
#include<algorithm>
#include<cctype>
#include<ctime>
#include <cmath>
#define CLOCKS_PER_SEC ((clock_t)1000)
using namespace std;
//线性表类
class Linklist {
//链表结点
struct Node {
string WordName;
int count;
Node*next;
Node* pre;
};
private:
Node* head=new Node;//头结点
int wordNum;//当前单词数
int Initial_wordNum;//总计单词数
public:
Linklist() {
head->next = head;
head->pre = head;
wordNum = 0;
}
//查找单词
Node* SearchWord(string word, Node* head) {
Node* ptr = head->next;
while (ptr != head) {
if (ptr->WordName == word)return ptr;
ptr = ptr->next;
}
return nullptr;
}
//读取文件并识别单词,已有则+1次数,没有则将该词加入链表
void Creat () {
cout << "读取Infile.txt文件\n";
ifstream input("Infile.txt");
if (input.fail())
{
cout << "不存在该文件" << endl;
cout << "退出程序" << endl;
exit;
}
string str;
int count;
char c;
//循环读取txt中的每一个字符
while (input.get(c))
{
if ((65<=c&&c<=90)||(c>=97&&c<=122)) //只考虑字母
str += c;
else
{
if (str != "")//已经识别为一个单词
{
transform(str.begin(), str.end(), str.begin(), ::tolower); //将所有字母转换为小写,以免记录根据大小写的不同重复记录单词
Node* temp=SearchWord(str, head); //线性搜索链表,查找单词
if(temp!=nullptr)temp->count++;
else {
Node* NewNode = new Node;
NewNode->count = 1;
NewNode->WordName = str;
head->next->pre = NewNode;
NewNode->next = head->next;
NewNode->pre = head;
head->next = NewNode;
wordNum++;
Initial_wordNum++;
}
}
str = ""; //单词尚未结束
}
}
if (input.is_open())
input.close();
cout << "------------------------------------\n";
}
//删除出现次数低于5的单词
void Delete() {
Node* ptr = head->next;
vector<Node>deleteNode;
while (ptr != head) {
bool flag = 1;
if (ptr->count < 5) {
Node* temp = new Node;
temp = ptr;
deleteNode.push_back(*temp);
ptr->pre->next = ptr->next;
ptr->next->pre = ptr->pre;
temp = ptr;
ptr = ptr->next;
delete temp;
wordNum--;
flag = 0;
}
if(flag)ptr = ptr->next;
}
cout << "删除频率低于5的的单词:\n";
for (auto x : deleteNode)cout << x.WordName << "("<<x.count<<") ";
cout <<"\n---------------------------------------------\n";
}
//将链表中的单词按频率从高到低输出到文件中
void Outfile() {
cout << "将其余单词与出现频率从高到低输入到G:\\Outfile.txt文件中\n";
ofstream outfile("G:\\Outfile.txt", std::ios::app);
while (head->next != head)