目录
实验要求
代码展示
界面展示
函数列表
实验报告及总结
问题与解决方法
尚存在的问题
总结
核心代码
各种数据结构的对比
收获和体会
实习题目: 基于不同策略的英文单词的词频统计和检索系统
实习环境:
实习内容:
一篇英文文章存储在一个文本文件中,然后分别基于线性表、二叉排序树和哈希表不同的存储结构,完成单词词频的统计和单词的检索功能。同时计算不同检索策略下的平均查找长度ASL,通过比较ASL的大小,对不同检索策略的时间性能做出相应的比较分析(比较分析要写在实习报告中的“收获和体会”中)。
实习要求
1. 读取一篇包括标点符号的英文文章(InFile.txt),假设文件中单词的个数最多不超过5000个。从文件中读取单词,过滤掉所有的标点。
2. 分别利用线性表(包括基于顺序表的顺序查找、基于链表的顺序查找、折半查找)、二叉排序树和哈希表(包括基于开放地址法的哈希查找、基于链地址法的哈希查找)总计6种不同的检索策略构建单词的存储结构。
3. 不论采取哪种检索策略,完成功能均相同。
(1)词频统计
当读取一个单词后,若该单词还未出现,则在适当的位置上添加该单词,将其词频计为1;若该单词已经出现过,则将其词频增加1。统计结束后,将所有单词及其频率按照词典顺序写入文本文件中。其中,不同的检索策略分别写入6个不同的文件。
基于顺序表的顺序查找--- OutFile1.txt
基于链表的顺序查找--- OutFile2.txt
折半查找--- OutFile3.txt
基于二叉排序树的查找--- OutFile4.txt
基于开放地址法的哈希查找--- OutFile5.txt
基于链地址法的哈希查找--- OutFile6.txt
注:如果实现方法正确,6个文件的内容应该是一致的。
(2)单词检索
输入一个单词,如果查找成功,则输出该单词对应的频率,同时输出查找成功的平均查找长度ASL和输出查找所花费的时间。如果查找失败,则输出“查找失败”的提示。
实习提示
不同的检索策略所采取的数据结构不一样,算法实现的过程不一样,但查找结果是一样的。
下面给出系统运行的部分参考截图。
主页面结果如图1所示。
图1
对于图1,选择1后进入“基于线性表的查找”,结果如图2所示。
图2
对于图2,选择1后进入“顺序查找”,结果如图3所示。
图3
对于图3,选择1后进入“基于顺序表的顺序查找”,结果如图4所示。
图4
对于图4,选择1后进入“词频统计”,完成词频统计功能。要求统计出所有单词的总数和每个单词的词频。统计结果全部输出到对应的文件OutFile1.txt中,该文件中的数据总计n+1行 ,第一行n为所有单词的总数,后面n行为每个单词及其出现的频率(单词和频率用空格分隔)。
文件OutFile1.txt的示例如图5所示。
图5
对于图4,选择2后进入“单词查找”,输入待查找的单词后,如果查找成功,结果如图6所示。首先显示此单词的词频,之后分别给出查找该单词所花的时间(单位为毫秒或微秒或纳秒,可以利用高精度的时间函数做计算来实现)和平均查找长度。如果查找失败,结果如图7所示。
图6
图7
对于其他5种检索策略,查找结果同图6或图7所示,只是在查找成功时所花的时间和平均查找长度不同而已。
选做内容:
1. 用窗体版界面取代控制台界面。
2. 程序中所用的到排序算法选用先进的排序算法(快速排序或归并排序或堆排序)。
3. 实现低频词过滤功能,要求将出现频率(词频/单词总数)低于10%的单词删除,可以选择不同的存储结构分别实现。
(1)顺序表
(2)链表
(3)二叉排序树
(4)基于开放地址法的哈希表
(5)基于链地址法的哈希表
实习任务阶段性安排
周一:
周二:
周三:
周四:
#include
#include
#include
#include
#include
#include
#include //要用到格式控制符
#define MAXSIZE 5000
#define m 5000 //哈希表的表长
#define NULLKEY " " //单元为空的标记
using namespace std;
int t;//单词总数
int factnum;//去重后单词数
string str[MAXSIZE];//存放单词
int fre[MAXSIZE];//存放词频
int flag[MAXSIZE];//标记第一次出现的位置
double rate[MAXSIZE];
int setrate=100;//万分之100以下的单词过滤
int setrate2;
typedef struct{
string key;
int Time;
}Word;
typedef struct{
Word *R;
int length;
}SSTable;
typedef struct LNode
{
Word data;
struct LNode *next;
}LNode,*LinkList;
typedef struct BSTNode
{
Word data;
struct BSTNode *lchild,*rchild;
}BSTNode,*BSTree;
BSTree T1;//
struct HashTable{
string key;
int Time;
};
typedef struct WordNode//单词结点
{
Word data;
struct WordNode *nextarc;
}WordNode;
typedef struct LetterNode//首字母表头结点
{
int letter_no;//ch
WordNode *firstarc;
}LetterNode,AdjList[38];//?
typedef struct
{
AdjList Letter;//Letter
}ALGraph;//邻接表
int Hash_int(int a)
{
int p;
p=str[a][0];
p=p-96;
return p;
}
void InitTree(BSTree &T)
{
T=new BSTNode;
T=NULL;
return;
}
void Insert(BSTree &T,Word e)
{
if(!T)
{
//建立一个根节点指针S并开辟存储空间
BSTree S;
S=new BSTNode;
//为新结点S赋值
S->data=e;
//初始化孩子左右结点为空
S->lchild=S->rchild=NULL;
T=S; //S赋值给T
}
else if(e.keydata.key)//如果待插入元素小于根节点,插入左边
Insert(T->lchild,e);
else if(e.key>T->data.key)//大于,右边
Insert(T->rchild,e);
}
int Input3(BSTree &T,string key){
int n=0;
if(T==NULL)return -1;
while(T!=NULL&&key!=T->data.key)//非递归遍历
{
n++;
if (keydata.key)
T=T->lchild;
else
T=T->rchild;
}
if(T==NULL)return -1;
if(key==T->data.key)
{
T->data.Time++;
return n;
}
}
int Search5(BSTree &T,string key){
int n=0;
if(T==NULL)return -1;
while(T!=NULL&&key!=T->data.key)
{
n++;
if (keydata.key)
T=T->lchild;
else
T=T->rchild;
}
if(T==NULL)return -1;
if(key==T->data.key)
{
return n;
}
}
void InputTree(BSTree &T)
{
int i=1;
//建立一颗空树
T=NULL;
//建立一个word结点,先赋值,便于录入
Word e;
e.key=str[1];
e.Time=1;
while(idata.Time++;//不行
//下一次的输入
i++;
e.key=str[i];
e.Time=1;//初次输入,词频都为1
}
}
int TraverseOut(BSTree T)
{
fstream out;
out.open("OutFile3.txt",ios::app);
if(T)
{
TraverseOut(T->lchild);
//cout<data.key<<" "<data.Time<data.key<<" "<data.Time<rchild);
}
return 0;
}
int TraverseOut2(BSTree T)
{
if(T)
{
TraverseOut2(T->lchild);
cout<data.key<<" "<data.Time<rchild);
}
return 0;
}
void Output3(BSTree T)
{
int i;
fstream out;
out.open("OutFile3.txt",fstream::out | ios_base::trunc);
out<<"单词 词频"<>ch;
BSTree temp;
InitTree(temp);
temp=T;
LARGE_INTEGER fr;
LARGE_INTEGER st;
LARGE_INTEGER ed;
double time;
QueryPerformanceFrequency(&fr);
QueryPerformanceCounter(&st);
int res=Search5(temp,ch);
QueryPerformanceCounter(&ed);
time = (double)(ed.QuadPart - st.QuadPart) / (double)fr.QuadPart;
if(res!=-1)
{
cout<<"此单词的词频为:"<data.Time<data.Time<'9'&&!CheckSqList(L,str[i])))//不重复录入
{
L.length++;
L.R[L.length].key=str[i];
L.R[L.length].Time=1;//不能++
//标记位置
flag[i]=1;
}
else if((str[i][0]<'0'&&CheckSqList(L,str[i]))||(str[i][0]>'9'&&CheckSqList(L,str[i])))//重复就只统计
{
L.R[CheckSqList(L,str[i])].Time++;//词频统计
}
i++;
}
}
void Rate1(SSTable L)
{
fstream out;
out.open("OutFile1.txt",fstream::out | ios_base::trunc);
int i=0;
cout<<"单词"<<" "<<"频次"<<" "<<"概率(万分之一)"<setrate)//&&rate[i]<100000
{
out<next){//遍历单链表
i++;
p=p->next;
if(p->data.key==a)
{
p->data.Time++;//有重复,频率加1
// cout<<"有重复,位置为"<next=NULL;
r=L;
for(i=1;i<=t;i++)
{
if(Locate(L,str[i])==0)
{
//未重复的部分,也就是第一次录入的部分
p=new LNode;
p->data.Time=1; //结点初始化频次为1
p->data.key=str[i];
p->next=NULL;
r->next=p;
r=p;
}
}
return;
}
void Rate2(LinkList L)
{
fstream out;
out.open("OutFile1.txt",fstream::out | ios_base::trunc);
LinkList p=L->next;
//利用顺序表计算单词概率
int i=1;
cout<<"单词"<<" "<<"频次"<<" "<<"概率"<data.Time;
rate[i]=(double)fre[i]/t;
rate[i]=rate[i]*10000;
if(rate[i]>setrate)
{
out<data.key<<" "<data.key<<" "<next) p=p->next;
else break;
}
i++;
}
}
int InitList(LinkList &L)
{
LinkList p=L;
while(p->next){
p=p->next;
p->data.Time=1;
}
return 0;
}
int ListLength(LinkList L)
{
LinkList p;
p=L->next; //p指向第一个结点
int i=0;
while(p){//遍历单链表,统计结点数
i++;
p=p->next;
}
return i;
}
void Sort2(LinkList &L)
{
int n=ListLength(L);
int i; //用i记录已经比好,置于末尾的元素
int j;//用j记录已比较的轮次
LinkList p;
for(i=0;inext;
j=0;//比较完一轮后,j归零
while(p&&jdata.key > p->next->data.key)
{
Word t=p->data;
p->data=p->next->data;
p->next->data=t;
}
p=p->next;
j++;
}
}
return;
}
void Output2(LinkList &L)
{
int i;
fstream out;
out.open("OutFile2.txt",fstream::out | ios_base::trunc);
out<<"单词 词频"<next;
while(p)
{
out<data.key<<" "<data.Time<next;
}
return;
}
void Search2(LinkList L)
{
Output2(L);
cout<<"基于链式存储结构,请输入你要查找的单词:" <>ch;
LARGE_INTEGER fr;
LARGE_INTEGER st;
LARGE_INTEGER ed;
double time;
QueryPerformanceFrequency(&fr);
QueryPerformanceCounter(&st);
LinkList p;
p=L;
int i=0;
while(p->next)
{
p=p->next;
if(p->data.key==ch)
{
QueryPerformanceCounter(&ed);
time = (double)(ed.QuadPart - st.QuadPart) / (double)fr.QuadPart;
cout<<"此单词的词频为:"<data.Time<next)
{
p=p->next;
if(p->data.key==ch)
{
QueryPerformanceCounter(&ed);
time = (double)(ed.QuadPart - st.QuadPart) / (double)fr.QuadPart;
cout<<"此单词的词频为:"<data.Time<>str[i];
int j=str[i].length();//单词字母数
//首字母大写转为小写
for(int n=0;n='A'&&str[i][n]<='Z')
str[i][n]=str[i][n]+32;
}
//非字母字符标记统计
int num=0;
for(int n=0;n'z')
{
//cout<<"非字母:"<800)cout<<"注意:当前单词数量过多,可能导致程序崩溃"<800)cout<<"注意:当前单词数量过多,可能导致程序崩溃"<800)cout<<"注意:当前单词数量过多,可能导致程序崩溃"<= x.key) // 从右向左找第一个小于x的数
j--;
if(i < j)
L.R[i++] = L.R[j];
while(i < j && L.R[i].key < x.key) // 从左向右找第一个大于等于x的数
i++;
if(i < j)
L.R[j--] = L.R[i];
}
L.R[i] = x;
QuickSort1(L, l, i - 1); // 递归调用
QuickSort1(L, i + 1, r);
}
}
void Sort1(SSTable &L)
{
int i=0,j=0;//外i内j
for(i=1;i<=L.length;i++)//外层循环n-1
for(j=1;j<=L.length-i;j++)//内层循环n-1-i
{
if(L.R[j].key>L.R[j+1].key)
{
Word temp;
temp=L.R[j];
L.R[j]=L.R[j+1];
L.R[j+1]=temp;
}
}
}
void Del1(SSTable &L,int no)
{
no=no+1;
int i;
if(no>L.length||no<1)
{
cout<<"Sorry,the position to be deleted is invalid!"<ListLength(L)||no<1)
{
cout<<"Sorry,the position to be deleted is invalid!"<next;
j++;
}
q=p->next;
p->next=q->next;
delete q;
return;
}
void DelLowRate2(LinkList &L)
{
cout<<"删除前表长:"<next)
{
i++;
p=p->next;
if(10000*(double)p->data.Time/t<100)
{
Del2(L,i);
i--;//key
}
}
cout<<"删除后表长:"<next)
{
p=p->next;
if(10000*(double)p->data.Time/t)
{
cout<<"剩余"<data.key<<" "<data.Time<<" "<<10000*(double)p->data.Time/t<rchild==NULL)
{
q = p; p = p->lchild; free(q);cout<<"删除完成1"<lchild==NULL)
{
q = p; p = p->rchild; free(q);cout<<"删除完成2"<lchild;
while (s->rchild)
{
q = s; s = s->rchild;
}
p->data = s->data;
if (q != p)
q->rchild = s->lchild;
else
q->lchild = s->lchild;
free(s);
cout<<"删除完成3"<data.key)
{
return Delete(T);
}
else if (keydata.key)
{
return DeleteBST(T->lchild,key);
}
else
{
return DeleteBST(T->rchild,key);
}
}
}
void DeleteBST2(BSTree &T,string key) {
//从二叉排序树T中删除关键字等于key的结点
BSTree p=T;BSTree f=NULL; //初始化
BSTree q;
BSTree s;
while(p)
{
if (p->data.key == key)
{
break;
}
f=p;
if (p->data.key> key)
{
p=p->lchild;
}
else
{
p=p->rchild;
}
}
if(!p)
{
return;
}
if ((p->lchild)&& (p->rchild))
{
q = p;
s = p->lchild;
while (s->rchild)
{q = s; s = s->rchild;}
p->data = s->data;
if(q!=p)
{
q->rchild = s->lchild;
}
else q->lchild = s->lchild;
delete s;
}//if
else
{
if(!p->rchild)
{
q = p;
p = p->lchild;
}//else if
else if(!p->lchild)
{
q = p; p = p->rchild;
}//else if
if(!f)
{
T=p;
}
else
{
if (q==f->lchild)
{
f->lchild = p;
}
else
{
f->rchild = p;
}
}
delete q;
}
}//DeleteBST
int DelLowRate3(BSTree &T)
{
if(T)
{
DelLowRate3(T->lchild);
if(10000*T->data.Time/t>100)
{
string key1=T->data.key;
//DeleteBST(T,key1);
Insert(T1,T->data);//Word e
factnum++;
}
else
{
// cout<<"保留:"<data.key<<" "<<10000*(double)T->data.Time/t<rchild);
}
return 0;
}
void MenuLinearList(SSTable &L)
{
//菜单
system("cls");
PrintMenu1();
char ch;
cin>>ch;
//Sort1(L);
QuickSort1(L,1,L.length);
Output1(L);//输出
string sk;
switch(ch)
{
case '1': cout<<"顺序查找,输入你要查找的单词:"<>sk;
Search1_Order(L,sk);system("pause");system("cls");break;
case '2': cout<<"折半查找,输入你要查找的单词:"<>sk;
Search1_Half(L,sk);system("pause");system("cls");
break;
case '3': DelLowRate1(L);system("pause");system("cls");break;
case '4': return;
}
}
int Hash(string key)
{
int n;
n=key[0]-'a';//用ASCII码作差,计算首字母的序号
int result=100*n;//每一个字母分配100个数组空间,a序号就是0,空间为0-100.
return result;
}
int Search4(HashTable HT[],string key){
//在哈希表中查找,若查找成功,返回序号,否则返回-1
int H0=Hash(key); //计算哈希地址
int Hi;
if (HT[H0].key==NULLKEY) return -1; //若单元H0为空,则所查元素不存在
else if (HT[H0].key==key) return H0; //若单元H0中元素的关键字为key,则查找成功
else{
for(int i=1;i= x.key) // 从右向左找第一个小于x的数
j--;
if(i < j)
HT[i++] = HT[j];
while(i < j && HT[i].key < x.key) // 从左向右找第一个大于等于x的数
i++;
if(i < j)
HT[j--] = HT[i];
}
HT[i] = x;
QuickSort(HT, l, i - 1); // 递归调用
QuickSort(HT, i + 1, r);
}
}
void Sort4(HashTable HT[])
{
int i=0;int j;int res=0;
for(i=0;i<=26;i++)
{
for(j=i*100+1;j<(i+1)*100;j++)
{
if (HT[j].key=="\0")
{
res=j;
break;
}
}
QuickSort(HT,i*100+1,res);//不能为(i+1)*100,因为后面都是空,只能到res
}
return;
}
void Output4(HashTable HT[])
{
int i;
fstream out;
out.open("OutFile4.txt",fstream::out | ios_base::trunc);
out<<"单词 词频"<>sk;
LARGE_INTEGER fr;
LARGE_INTEGER st;
LARGE_INTEGER ed;
double time;
QueryPerformanceFrequency(&fr);
QueryPerformanceCounter(&st);
int result=Search4(HT,sk);
QueryPerformanceCounter(&ed);
time = (double)(ed.QuadPart - st.QuadPart) / (double)fr.QuadPart;
if(result!=-1)
{
cout<<"此单词的词频为:"<data.key<<" "<data.Time<nextarc;
}
}
out.close();
return;
}
void Sort5(ALGraph &G)
{
int i;
for(i=1;i<=26;i++)
{
WordNode *p,*q;
Word t;
for (p=G.Letter[i].firstarc; p!=NULL; p=p->nextarc)
{
for(q=p->nextarc; q!=NULL; q=q->nextarc)
{
if(p->data.key>q->data.key)
{
t=q->data;
q->data=p->data;
p->data=t;
}
}
}
}
return;
}
void HashChainAddress(ALGraph G,string sk)
{
cout<<"基于链地址法:"<data.key==sk)
{
flag=j;
r=h->data.Time;
}
h=h->nextarc;
}
QueryPerformanceCounter(&ed);
time = (double)(ed.QuadPart - st.QuadPart) / (double)fr.QuadPart;
if(flag>0)
{
cout<<"此单词的词频为:"<data.key=str[i];
p->data.Time=fre[i];
p->nextarc=NULL;
G.Letter[k].firstarc=p;
num++;
}
else
{
int flag=0;
while(h!=NULL)
{
r=h;
if(h->data.key==str[i])//遍历一个首字母的链表,如果相同,频次自加
{
h->data.Time++;
flag=1;
}
h=h->nextarc;//
}
if(flag==0)//如果没有相同的,就录入
{
p=new WordNode;
p->data.key=str[i];
p->data.Time=fre[i];
p->nextarc=NULL;
r->nextarc=p;
num++;
}
}
}
factnum=num;//有效单词数
return;
}
void MenuHash(HashTable HT[],ALGraph G)
{
//菜单
system("cls");
PrintMenu4();
char ch;
cin>>ch;
string sk;
switch(ch)
{
case '1': HashOpenAddress(HT);system("pause");system("cls");break;
case '2': cout<<"链地址法,输入你要查找的单词:"<>sk;
HashChainAddress(G,sk);system("pause");system("cls");
break;
case '3': return;
}
}
void PrintMenu7()
{
cout<<"基于不同策略的英文单词的词频统计和检索系统"<800)cout<<"注意:当前单词数量过多,可能导致程序崩溃"<lchild,i);
i++;
if(10000*(double)T->data.Time/tdata.key<<" "<data.Time<data.key<<" "<data.Time<<"/"<data.Time/t<rchild,i);
}
return 0;
}
void Rate3(BSTree T)
{
int i=0;
cout<<"单词"<<" "<<"频次"<<" "<<"概率(万分之一)"<setrate)
{
out<data.Time/t>setrate)
{
out<data.key<<" "<data.Time<data.key<<" "<data.Time<<"/"<data.Time/t<nextarc;
k++;
}
}
return;
}
void Rate6(SSTable L)
{
cout<<"请输入筛选的概率区间:"<>setrate>>setrate2;
int i=0;//fre[5]=1;
cout<<"单词"<<" "<<"频次"<<" "<<"概率(万分之一)"<setrate&&rate[i]>ch;
string sk;
switch(ch)
{
case '1': Rate1(L);system("pause");system("cls");break;
case '2': Rate2(L1);system("pause");system("cls");break;
case '3': Rate3(T);system("pause");system("cls");break;
case '4': Input4(HT);system("pause");system("cls");Sort4(HT);Rate4(HT);break;
case '5': Rate5(G);system("pause");system("cls");break;
case '6': Rate6(L);system("pause");system("cls");break;
}
}
void Compare(SSTable L,LinkList L1,BSTree T,HashTable HT[],ALGraph G)
{
cout<<"请输入您要查找的单词:"<>sk;
Sort1(L);
Sort2(L1);
Sort4(HT);
Sort5(G);
Search1_Order(L,sk);cout<>ch;
switch(ch)
{
case '1':MenuLinearList(L);break;
case '2':Search2(L1);system("pause");system("cls");break;break;
case '3':Search3(T);system("pause");system("cls");break;break;
case '4':MenuHash(HT,G);break;
case '5':cout<<"单词总数:"<
窗体还没写。每个句子之间必须隔开,有一个空格。
BSTree temp;
InitTree(temp);
temp=T;
int res=InputCheck3(temp,str[i]);
Int 查重函数()
{
如果重复,频率加1,返回一个标记值。
如果不重复,返回另一个标记值
}
While(未录入完毕)
{
If(查重函数说没有重复)
{
录入新单词;
设置单词频率为1;
}
}
在对链表进行遍历操作的时候,建立一个临时的指针,让它等于待操作链表,防止对原链表进行修改。
对于自加的变量,一定要先进行初始化。p->data.Time++;
int i=1;
while(i<=单词总数100)
{
输出序号,输出单词;
i++;
}
cout<<"除去数字外,本文一共"<
For/while(循环条件)
{
if(找到)
{
flag=1;
break;
}
}
if(flag==1)
{
输出查找成功;
}
else 输出查找失败;
印象中,设置标志变量flag并break,可以避免某些查不出来的错误。
函数类型 函数名(数组类型 数组名[]);
Void OpenAddressing(HashTable HT[]);
函数名(数组名);
OpenAddressing(HT);
Char ch;
Cin>>ch;
switch(ch)
{
case '1':MenuLinearList(L);break;
case '2':LinkListSearch(L1);break;
case '3':BinaryTreeSearch(T);break;
}
Break不能少。
Case后面是单引号。
void Input5(ALGraph &G)
{
int i;
//初始化顶点表
for(i=1;i<=26;i++)
{
G.Letter[i].letter_no=i;
G.Letter[i].firstarc=NULL;
}
int num=0;//单词计数
for(i=0;idata.key=str[i];
p->data.Time=fre[i];
p->nextarc=NULL;
G.Letter[k].firstarc=p;
num++;
}
else
{
int flag=0;
while(h!=NULL)
{
r=h;
if(h->data.key==str[i])//遍历一个首字母的链表,如果相同,频次自加
{
h->data.Time++;
flag=1;
}
h=h->nextarc;//
}
if(flag==0)//如果没有相同的,就录入
{
p=new WordNode;
p->data.key=str[i];
p->data.Time=fre[i];
p->nextarc=NULL;
r->nextarc=p;
num++;
}
}
}
factnum=num;//有效单词数
return;
}
void Preprocessing()
{
//读入
fstream in;
in.open("InFile.txt",ios::in);
if(!in)
{
cout<<"Can not open the file!"<>str[i];
int j=str[i].length();//单词字母数
//首字母大写转为小写
for(int n=0;n='A'&&str[i][n]<='Z')
str[i][n]=str[i][n]+32;
}
//非字母字符标记统计
int num=0;
for(int n=0;n'z')
{
//cout<<"非字母:"<
while(T!=NULL&&key!=T->data.key)//非递归遍历
{
n++;
if (keydata.key)
T=T->lchild;
else
T=T->rchild;
}
int t;//单词总数
int factnum;//去重后单词数
string str[MAXSIZE];//存放单词
int fre[MAXSIZE];//存放词频
int flag[MAXSIZE];//标记第一次出现的位置
double rate[MAXSIZE];
int setrate=100;//万分之100以下的单词过滤
int setrate2;
typedef struct{
string key;
int Time;
}Word;
typedef struct{
Word *R;
int length;
}SSTable;
typedef struct LNode
{
Word data;
struct LNode *next;
}LNode,*LinkList;
typedef struct BSTNode
{
Word data;
struct BSTNode *lchild,*rchild;
}BSTNode,*BSTree;
struct HashTable{
string key;
int Time;
};
typedef struct WordNode//单词结点
{
Word data;
struct WordNode *nextarc;
}WordNode;
typedef struct LetterNode//首字母表头结点
{
int letter_no;
WordNode *firstarc;
}LetterNode,AdjList[5000];//??
typedef struct
{
AdjList Letter;//Letter
}ALGraph;//邻接表
fstream in;
in.open("InFile.txt",ios::in);
if(!in)
{
cout<<"Can not open the file!"<
while(!in.eof())
fstream out;
out.open("OutFile1.txt",fstream::out | ios_base::trunc);
#include
LARGE_INTEGER fr;
LARGE_INTEGER st;
LARGE_INTEGER ed;
double time;
QueryPerformanceFrequency(&fr);
QueryPerformanceCounter(&st);
QueryPerformanceCounter(&ed);
time = (double)(ed.QuadPart - st.QuadPart) / (double)fr.QuadPart;
if(str[i][0]=='\0')
{
i--;//如果当前接收的是一个空串,则接受下一个字符串
}
i++;
//频率数组初始化
for(i=1;i
void QuickSort1(SSTable &L, int l, int r)//l=1,r=L.length
{
if (l < r)
{
//Swap(s[l], s[(l + r) / 2]); //将中间的这个数和第一个数交换
int i=l, j=r;Word x = L.R[l];
while (i < j)
{
while(i < j && L.R[j].key>= x.key) // 从右向左找第一个小于x的数
j--;
if(i < j)
L.R[i++] = L.R[j];
while(i < j && L.R[i].key < x.key) // 从左向右找第一个大于等于x的数
i++;
if(i < j)
L.R[j--] = L.R[i];
}
L.R[i] = x;
QuickSort1(L, l, i - 1); // 递归调用
QuickSort1(L, i + 1, r);
}
}
int i=0,j=0;//外i内j
for(i=1;i<=L.length;i++)//外层循环n-1 +1
for(j=1;j<=L.length-i;j++)//内层循环n-1-i+1
10000*(double)L.R[i].Time/t
int Hash(string key)
{
int n;
n=key[0]-'a';//用ASCII码作差,计算首字母的序号
int result=100*n;//每一个字母分配100个数组空间,a序号就是0,空间为1-100.
return result;
}
void Sort4(HashTable HT[])
{
int i=0;int j;int res=0;
for(i=0;i<=26;i++)
{
for(j=i*100+1;j<(i+1)*100;j++)
{
if (HT[j].key=="\0")
{
res=j;
//cout<<"i:"<
头文件 include
定义文件流 fstream in
打开 in.open(“1.txt”,ios::in)
打开方式 ios::app 可以从上次读的地方接着读
while(!in.eof()) 没有读到文件的末尾,循环就会继续。
#include
str[i].length();
//字符串可以直接比大小。
str[i][n]>='A'???
str[i][n]=str[i][n]+32;
str[i][n]=35;
//截取字符串的函数
str[i].substr(0,j-num);
system("pause");
system("cls");
T=new BSTNode;
T=NULL;
typedef struct BSTNode
{
Word data;
struct BSTNode *lchild,*rchild;
}BSTNode,*BSTree;
//BSTree 指针
//开辟存储空间用BSTNode
首次录入设置频率为1。设为1是初始化,很重要。
再次录入时,查找数据结构,不录入,频率自加。
当程序崩溃时,在程序的不同位置,cout相应的标志。
以检查崩溃的原因。没有输出结果,有以下几种常见原因:
1.死循环
死循环的原因,有函数层层嵌套导致的逻辑错误。
函数A调用函数B,但是函数B里又要调用函数A。
2.未初始化
建立一个二叉树需要先初始化,先有init函数然后才能有create函数。
T=new BSTNode;
T=NULL;
3.指针越界
While(p->next)
对于多种数据结构,由2的图中数据可以分析出来,二叉排序树和顺序表的折半查找是最快的,平均查找长度也是最小的。
1672行代码!
一个星期没日没夜的编程,让我深刻地理解了“码农”。
我不算一个聪明和优秀的学生,写得相对慢一些。
一天敲代码17个小时,早上7点半到机房,凌晨回宿舍还在写。实际上大部分时间都在debug。
一个bug的出现,有可能是逻辑错误,也有可能是符号或者语句的错误。
编程的时候逻辑一定要清晰,最好能写出伪代码,这样能大大提高编程效率。
一定要细心细心再细心,任何一个微小的地方,都有可能导致整个程序的崩溃。
比如if语句中的等号(==),不能写成赋值符号(=),最好是把数字写在前面(-1==res)。
对于函数的命名,不要用相同的名字,最好按照菜单的序号,在具体的名字后加数字。用英文名,不要用拼音。
命名应该规范。比如Menu类函数,menu应该放前面。
对于编译器应该有更多的了解。
比如要用时钟函数,需要c++11。Devc++是可以支持c++11的,只需要在设置里改一下就行了。
在最后要特别感谢小双,这次课设是和小双一起在机房完成的。
不论是这次课设,还是平常的时候,她都一直支持、鼓励我坚持下去。
不然我早就转专业,不学计算机了哈哈,还好还好坚持下来了。