日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

数据结构 C++实现 基于不同策略的英文单词的词频统计和检索系统(糅合版)

發(fā)布時間:2024/8/1 c/c++ 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数据结构 C++实现 基于不同策略的英文单词的词频统计和检索系统(糅合版) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

文章目錄

  • 一、實驗目的
  • 二、設(shè)計內(nèi)容
  • 三、測試數(shù)據(jù)
  • 四、設(shè)計思路
  • 五、代碼內(nèi)容
    • 1、函數(shù)運行時間(高精度)
    • 2、函數(shù)運行時間(低精度)
    • 3、代碼實現(xiàn)
  • 六、運行結(jié)果
  • 七、總結(jié)

一、實驗目的

1、掌握基于線性表、二叉排序樹和散列表不同存儲結(jié)構(gòu)的查找算法。
2、掌握不同檢索策略對應(yīng)的平均查找長度(ASL)的計算方法,明確不同檢索策略的時間性能的差別。

二、設(shè)計內(nèi)容

一篇英文文章存儲在一個文本文件中,然后分別基于線性表、二叉排序樹和哈希表不同的存儲結(jié)構(gòu),完成單詞詞頻的統(tǒng)計和單詞的檢索功能。同時計算不同檢索策略下的平均查找長度ASL,通過比較ASL的大小,對不同檢索策略的時間性能做出相應(yīng)的比較分析(比較分析要寫在實習報告中的“收獲和體會”中)。

  • 讀取一篇包括標點符號的英文文章(InFile.txt),假設(shè)文件中單詞的個數(shù)最多不超過5000個。從文件中讀取單詞,過濾掉所有的標點。
  • 分別利用線性表(包括基于順序表的順序查找、基于鏈表的順序查找、基于順序表的折半查找)、二叉排序樹和哈希表(包括基于開放地址法的哈希查找、基于鏈地址法的哈希查找)總計6種不同的檢索策略構(gòu)建單詞的存儲結(jié)構(gòu)。
  • 不論采取哪種檢索策略,完成功能均相同。
    (1)詞頻統(tǒng)計
    當讀取一個單詞后,若該單詞還未出現(xiàn),則在適當?shù)奈恢蒙咸砑釉搯卧~,將其詞頻計為1;若該單詞已經(jīng)出現(xiàn)過,則將其詞頻增加1。統(tǒng)計結(jié)束后,將所有單詞及其頻率按照詞典順序?qū)懭胛谋疚募小F渲?#xff0c;不同的檢索策略分別寫入6個不同的文件。
    基于順序表的順序查找— OutFile1.txt
    基于鏈表的順序查找— OutFile2.txt
    折半查找— OutFile3.txt
    基于二叉排序樹的查找— OutFile4.txt
    基于開放地址法的哈希查找— OutFile5.txt
    基于鏈地址法的哈希查找— OutFile6.txt
    注:如果實現(xiàn)方法正確,6個文件的內(nèi)容應(yīng)該是一致的。
    (2)單詞檢索
    輸入一個單詞,如果查找成功,則輸出該單詞對應(yīng)的頻率,同時輸出查找成功的平均查找長度ASL和輸出查找所花費的時間。如果查找失敗,則輸出“查找失敗”的提示。
  • 三、測試數(shù)據(jù)

    我這里只是隨便找的比較短的一篇

    四、設(shè)計思路

    五、代碼內(nèi)容

    點擊這里有分塊寫的代碼

    1、函數(shù)運行時間(高精度)

    精度比較高

    #include<iostream> #include<thread> using namespace std ; using namespace chrono; //使用命名空間chrono template <typename T> //函數(shù)模板/* 關(guān)鍵詞 auto 看上去很高大上,它是一個“自動類型”,可以理解成“萬能類型”,想成為啥,就成為啥 system_clock 是 C++11 提供的一個 clock。除此之外,還有兩個clock:steady_clock 和 high_resolution_clock clock:時鐘 now( ) 表示計時的那“一瞬間” duration_cast< > 表示類型轉(zhuǎn)換 duration:持續(xù)時間 count( ) 用來返回時間 */ void measure(T&& func) {auto start = system_clock::now(); //開始時間func(); //執(zhí)行函數(shù)duration<double> diff = system_clock::now() - start; //現(xiàn)在時間 - 開始時間cout << "elapsed: " << diff.count() << "秒" << endl; }void func(){long long s = 0;for(int i=0;i<20000000;i++){s+=i;}cout<<s<<endl; } int main(){measure(func);return 0; }

    2、函數(shù)運行時間(低精度)

    精度比較低

    #include <ctime> #include <iostream> using namespace std;void func(){long long s = 0;for(int i=0;i<20000000;i++){s+=i;}cout<<s<<endl; } int main(){clock_t start = clock();func();clock_t end = clock();cout << "花費了" << (double)(end - start) / CLOCKS_PER_SEC << "秒" << endl; }

    3、代碼實現(xiàn)

    //寫一個標準的頭文件避免重復編譯 #ifndef _HEAD_H #define _HEAD_H/*#include <fstream>ofstream //文件寫操作 內(nèi)存寫入存儲設(shè)備ifstream //文件讀操作,存儲設(shè)備讀取到內(nèi)存中fstream //讀寫操作,對打開的文件可進行讀寫操作void open(const char* filename,int mode,int access);參數(shù):filename:  要打開的文件名mode:    要打開文件的方式access:   打開文件的屬性打開文件的方式在類ios(是所有流式I/O類的基類)中定義.常用的值如下:ios::app:   以追加的方式打開文件ios::ate:   文件打開后定位到文件尾,ios:app就包含有此屬性ios::binary: 以二進制方式打開文件,缺省的方式是文本方式。兩種方式的區(qū)別見前文ios::in:    文件以輸入方式打開(文件數(shù)據(jù)輸入到內(nèi)存)ios::out:   文件以輸出方式打開(內(nèi)存數(shù)據(jù)輸出到文件)ios::nocreate: 不建立文件,所以文件不存在時打開失敗ios::noreplace:不覆蓋文件,所以打開文件時如果文件存在失敗ios::trunc:  如果文件存在,把文件長度設(shè)為0 */#include<iostream> #include<thread> #include<fstream> #include<string> #include<ctime> #include<cmath> #include<Windows.h> using namespace std; using namespace chrono; //使用命名空間chrono//常量 const int MaxSize = 1000; //文章單詞最大容量 const char* file = "file.txt"; //待檢索文件 static int sum = 0; //單詞總數(shù)(不重復)// 結(jié)構(gòu)體// 詞頻順序存儲結(jié)構(gòu) struct WordFrequency { //詞頻string word; //單詞int frequency; //頻率int key; //關(guān)鍵碼 }WF[MaxSize];typedef WordFrequency datatype; //為數(shù)據(jù)類型定義一個新的名字//詞頻鏈式存儲結(jié)構(gòu) struct Node {datatype data; //數(shù)據(jù)域Node* next; //指針域 };//二叉排序樹鏈式存儲結(jié)構(gòu) struct BiNode {datatype data; //節(jié)點數(shù)據(jù)域BiNode* lchild, * rchild; //左右孩子指針 };//ReadFile函數(shù)聲明 int StatisticalWord(string word); //統(tǒng)計文章詞頻(去掉重復單詞) string WordTransition(string word); //大寫英語單詞轉(zhuǎn)化成小寫 int WordJudge(string word); //判斷單詞中是否有大寫字母 void StatisticsData(); //數(shù)據(jù)統(tǒng)計 int WordTransitionKey(string word); //將單詞轉(zhuǎn)換為唯一關(guān)鍵碼//LinkedListMenu函數(shù)聲明 void ListMenu(); // 線性表菜單 void SequenceMenu(); //順序查找菜單 void SeqListMenu(); //順序表順序查找菜單 void WorLocatMenu();//順序表單詞查找菜單 void LinklistSeqMenu();//鏈表順序查找菜單 void LinklistLocateMenu(); //鏈表單詞查找菜單 void HalfSortMenu(); //順序表折半查找菜單 void HalfdLocateMenu(); //順序表折半單詞查找菜單//BiTreeMenu函數(shù)聲明 void BiTreeMenu(); // 二叉排序樹菜單 void BitreeLocateMenu(); //二叉排序樹的順序查找菜單 void BitreeWordLocMenu(); //二叉排序樹查找單詞菜單//HashTableMenu函數(shù)聲明 void HashMenu(); //哈希表菜單 void OpenHashLocateMenu(); //開放地址法哈希查找菜單 void OpenHashLocate(); //開放地址法哈希查找 void LinkHashLocate(); //鏈地址法哈希查找 void LinkHashWordLocateMenu(); //開放地址法哈希查找菜單void MajorMenu(); //主菜單#endif // !_HEAD_H//主函數(shù) int main(){ifstream fin;fin.open(file);//關(guān)聯(lián)文件fileif (!fin.is_open()){cout << "file.txt文件不存在,請檢查文件名或者目錄下文件是否存在。" << endl;system("pause"); //暫停return 0;} //ifelse{cout << "file.txt文件加載中..." << endl;Sleep(1000);//延時1秒} //elseStatisticsData(); //數(shù)據(jù)統(tǒng)計MajorMenu();//主菜單return 0; }//主菜單 void MajorMenu(){while(true){system("cls"); //清屏cout << "*******************基于不同策略的英文單詞的詞頻統(tǒng)計和檢索系統(tǒng)*******************" << endl;cout << "---菜單---" << endl;cout << "1.基于線性表的查找" << endl;cout << "2.基于二叉排序樹的查找" << endl;cout << "3.基于哈希表的查找" << endl;cout << "4.退出系統(tǒng)" << endl;cout << "請按相應(yīng)的數(shù)字鍵進行選擇:" << endl;int n;cin >> n;switch (n){case 1: ListMenu();break;case 2:BiTreeMenu();break;case 3:HashMenu(); break;case 4: cout << "系統(tǒng)已退出" << endl; return;default: cout << "輸入的不是有效符號,請重新輸入" << endl; system("cls"); //清屏system("pause"); //暫停} //switch} //for }// 讀取TXT內(nèi)容并整理 //統(tǒng)計文章詞頻(去掉重復單詞) int StatisticalWord(string word){for (int i = 0; i < MaxSize; i++){ //循環(huán)控制,單詞查重if (WF[i].word == word){ //單詞重復WF[i].frequency++; //詞頻+1return i; //退出函數(shù)} //if} //for//單詞不重復WF[sum].word = word; //添加單詞WF[sum].frequency = 1; //詞頻置為一WF[sum].key = WordTransitionKey(word); //添加關(guān)鍵碼sum ++; //單詞總數(shù)+1return 0; }//大寫英語單詞轉(zhuǎn)化成小寫 string WordTransition(string word){for (int i = 0; i < int(word.size()); i++){ //獲取字符串長度,使用length()也可以if (word[i] >= 'A' && word[i] <= 'Z') //判斷字符是否是大寫字母word[i] = word[i] + 32; //ASCII碼表中十進制 A==65 a==97 中間相差32,后面的也是如此} //forreturn word; //返回小寫單詞 }//判斷單詞中是否有大寫字母 int WordJudge(string word){for (int i = 0; i < int(word.size()); i++){if (word[i] >= 'A' && word[i] <= 'Z') //判斷單詞中是否有大寫字母return 1; //如果有,返回1} //forreturn 0; //沒有返回0 }//詞頻統(tǒng)計 void StatisticsData(){system("cls"); //清屏ifstream fin; //文件讀操作,存儲設(shè)備讀取到內(nèi)存中fin.open(file); //關(guān)聯(lián)文件filechar ch; //用于獲取字符 string word; //用于存放單詞int count = 0,min; //count用于標記單詞個數(shù),min用于標記最小的單詞for (int i = 0; fin.get(ch); i++){ //讀取文件內(nèi)容,并去除符號if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')){if (word == "\0") //word為空,放入第一個字母word = ch;elseword += ch; //word不為空,拼接字母組成單詞} //ifelse{if (word != "\0"){ //判斷之前的word里面是否有單詞count++; //有單詞,總數(shù)+1if (count > MaxSize){cout << "文章單詞超出統(tǒng)計上限,系統(tǒng)已退出" << endl;fin.close(); //關(guān)閉文件exit(0); //退出程序system("pause"); //暫停}StatisticalWord(word); //存放到結(jié)構(gòu)體數(shù)組里面} //ifword = "\0"; //重置word,用于存放新單詞} //else} //for//按照詞典排序(選擇排序) 從小到大WordFrequency temp; //臨時存儲空間for (int i = 0; i < sum; i++){min = i; //重置minfor (int j = i + 1; j < sum; j++){if (WordTransition(WF[j].word) < WordTransition(WF[min].word)) //將單詞轉(zhuǎn)換成小寫進行比較min = j; //得到最小單詞序號} //for//交換原始單詞,詞頻temp = WF[i];WF[i] = WF[min];WF[min] = temp;} //forfor (int i = 0; i < sum; i++){min = i;for (int j = i + 1; j < sum; j++){if (WordTransition(WF[j].word) == WordTransition(WF[min].word)) //兩個單詞相等if (WordJudge(WF[j].word) > WordJudge(WF[min].word)) //大寫的排前面min = j; //得到最小單詞序號} //for//交換原始單詞,詞頻temp = WF[i];WF[i] = WF[min];WF[min] = temp;} //forfin.close(); //關(guān)閉文件 }//將單詞轉(zhuǎn)換為唯一關(guān)鍵碼 int WordTransitionKey(string word) {int a[21] = { 0,2,3,5,7,11,13,17,19,23,27,29,31,37,41,47,51,67,87,101,111 }; //最長識別20個字母的的單詞int sumkey = 0;for (int i = 0; i < int(word.size()); i++) {sumkey += int(word[i]); //每個字符的ASCLL值相加}sumkey += int('h') * a[int(word.size())];return sumkey; }//順序表類 class SeqList{public:SeqList() {} //無參構(gòu)造SeqList(datatype a[], int n){ //有參構(gòu)造函數(shù),初始化長度為n的順序表if (n > MaxSize){cout << "單詞數(shù)量過多,超出線性表最大容量" << endl;} //iffor (int i = 0; i < n; i++){wf[i].word = a[i].word;wf[i].frequency = a[i].frequency;} //for}~SeqList(){}; //析構(gòu)函數(shù)int Empty(); //順序表判空函數(shù)void PrintList(int n); //遍歷操作,按序號依次輸出各元素int SeqlistLocate(string word); //順序查找int BinSearch(string word); //折半查找string getword(int n); //返回單詞int getfre(int n); //返回詞頻private:datatype wf[MaxSize]; //存放詞頻結(jié)構(gòu)體的數(shù)組 };//返回單詞 string SeqList::getword(int n) {return wf[n].word; }//返回詞頻 int SeqList::getfre(int n) {return wf[n].frequency; }//順序表判空函數(shù) int SeqList::Empty(){if (sum == 0)return 1;elsereturn 0; }//順序查找 int SeqList::SeqlistLocate(string word){for (int i = 0; i < sum; i++){ //依次遍歷if (wf[i].word == word) //找到wordreturn i; //返回下標} //forreturn -1; //未找到返回-1 }//折半查找 int SeqList::BinSearch(string word){int mid, low = 0, high = sum - 1; //初始查找區(qū)間是[0, sum-1]while (low <= high) { //當區(qū)間存在時mid = (low + high) / 2; //初始化中值if (word == wf[mid].word) //找到wordbreak; //退出循環(huán)else if (WordTransition(word) < WordTransition(wf[mid].word)) //word在前半段high = mid - 1; //改變上限,gigh前移查找區(qū)間變?yōu)?[low,mid-1]else //word在后半段,或者不存在low = mid + 1; //改變下線,low后移查找區(qū)間變?yōu)?[mid+1,high]} //whileif (low <= high)return mid; //找到返回下標elsereturn -1; //未找到返回-1 }//輸出線性表順序表,參數(shù)n用來控制輸出順序查找還是折半查找 void SeqList::PrintList(int n){system("cls"); //清屏if (n == 1){ofstream fout; //文件寫操作 內(nèi)存寫入存儲設(shè)備 fout.open("outfile1.txt");fout << "單詞總數(shù)為:" << sum << endl;fout << "詞頻" << "\t" << "單詞" << endl;for (int i = 0; i< sum; i++){fout << wf[i].frequency << "\t" << wf[i].word << endl; } //forfout.close(); //關(guān)閉文件} //ifif (n == 2){ofstream fout; //文件寫操作 內(nèi)存寫入存儲設(shè)備 fout.open("outfile3.txt");fout << "單詞總數(shù)為:" << sum << endl;fout << "詞頻" << "\t" << "單詞" << endl;for (int i = 0; i < sum; i++) {fout << wf[i].frequency << "\t" << wf[i].word << endl;} //forfout.close(); //關(guān)閉文件} //ifcout << "單詞總數(shù)為:" << sum << endl;cout << "詞頻" << "\t" << "單詞" << endl;for (int i = 0; i < sum; i++)cout << wf[i].frequency << "\t" << wf[i].word << endl;if (n == 1)cout << "單詞以及詞頻已經(jīng)保存到文件outfile1.txt文件中" << endl;else if (n == 2)cout << "單詞以及詞頻已經(jīng)保存到文件outfile3.txt文件中" << endl;system("pause"); //暫停 }//鏈表類 class LinkList{public:LinkList(datatype a[], int n) { //有參構(gòu)造函數(shù),建立有n個元素的單鏈表Head = new Node; //生成頭結(jié)點Node* r = Head, * s = NULL; //尾指針初始化,并定義存儲指針for (int i = 0; i < n; i++){s = new Node; s->data = a[i]; //數(shù)據(jù)域賦值r->next = s; //將存儲節(jié)點s插入鏈表r = s; //更新尾指針} //forr->next = NULL; //單鏈表建立完畢,將終端結(jié)點的指針域置空}~LinkList() { //析構(gòu)函數(shù)Node* temp = NULL; //定義臨時節(jié)點while (Head != NULL){ //釋放單鏈表的每一個結(jié)點的存儲空間temp = Head; //暫存被釋放結(jié)點Head = Head->next; // Head指向被釋放結(jié)點的下一個結(jié)點delete temp;} //while}int Empety(); //判斷鏈表是否為空int Locate(string word); //按值查找,返回下標void PrintList(); //遍歷操作,按序號依次輸出各元素datatype getdata(int n);private:Node* Head; //單鏈表的頭指針 };//返回數(shù)據(jù)域 datatype LinkList::getdata(int n) {Node* t = Head->next; //指針初始化for (int i = 1; i < n; i++)t = t->next;return t->data;}//判空 int LinkList::Empety(){if (Head->next)return 1; //鏈表非空,正常返回return 0; //鏈表為空,返回-1 }//輸出單鏈表 void LinkList::PrintList(){system("cls"); //清屏Node* p = Head->next;//工作指針p初始化ofstream fout; //文件寫操作 內(nèi)存寫入存儲設(shè)備 fout.open("outfile2.txt"); //打開文件fout << "單詞總數(shù)為:" << sum << endl;fout << "詞頻" << "\t" << "單詞" << endl;while (p != NULL){fout << p->data.frequency << "\t" << p->data.word << endl;p = p->next; //指針p后移} //whilefout.close(); //關(guān)閉文件cout << "單詞總數(shù)為:" << sum << endl;cout << "詞頻" << "\t" << "單詞" << endl;Node* p1 = Head->next;//工作指針p初始化while (p1){ //p <--> p != NULLcout << p1->data.frequency << "\t" << p1->data.word << endl;p1 = p1->next; //工作指針p后移,注意不能寫作p++} //whilecout << "單詞以及詞頻已經(jīng)保存到文件outfile2.txt文件中" << endl;system("pause"); //暫停 }//按值查找,返回下標 int LinkList::Locate(string word){Node* p = Head->next; //指針p初始化int count = 1; //計數(shù)器count初始化,表示查找次數(shù)while (p != NULL){if (p->data.word == word) return count; //查找成功,結(jié)束函數(shù)并返回下標p = p->next; //p指針后移count++;} //whilereturn -1; //退出循環(huán)表明查找失敗 }// 線性表菜單 void ListMenu(){while(true) {system("cls"); //清屏cout << "*******************基于不同策略的英文單詞的詞頻統(tǒng)計和檢索系統(tǒng)*******************" << endl;cout << "---基于線性表的查找---" << endl;cout << "1.順序查找" << endl;cout << "2.折半查找" << endl;cout << "3.返回上一級" << endl;cout << "請按相應(yīng)的數(shù)字鍵進行選擇:" << endl;int n;cin >> n;switch (n){case 1 : SequenceMenu(); //順序查找菜單break;case 2 : HalfSortMenu(); //順序表折半查找菜單break;case 3 : return; //結(jié)束函數(shù)default: cout << "輸入的不是有效符號,請重新輸入" << endl; system("pause"); //暫停} //switch} //while }//順序查找菜單 void SequenceMenu(){while(true){system("cls"); //清屏cout << "*******************基于不同策略的英文單詞的詞頻統(tǒng)計和檢索系統(tǒng)*******************" << endl;cout << "---順序查找---" << endl;cout << "1.順序表查找" << endl;cout << "2.鏈表順序查找" << endl;cout << "3.返回上一級" << endl;cout << "請按相應(yīng)的數(shù)字鍵進行選擇:" << endl;int n;cin >> n;switch (n){case 1:SeqListMenu(); //順序查找菜單break;case 2: LinklistSeqMenu(); //鏈表查找菜單break;case 3: return; //結(jié)束函數(shù)default:cout << "輸入的不是有效符號,請重新輸入" << endl;system("pause"); //暫停break;} //switch} //while }//順序表順序查找菜單 void SeqListMenu(){SeqList L(WF, sum);while(true){system("cls");cout << "*******************基于不同策略的英文單詞的詞頻統(tǒng)計和檢索系統(tǒng)*******************" << endl;cout << "---順序表順序查找---" << endl;cout << "1.詞頻統(tǒng)計" << endl;cout << "2.單詞查找" << endl;cout << "3.返回上一級" << endl;cout << "請按相應(yīng)的數(shù)字鍵進行選擇:" << endl;int n;cin >> n;switch (n){case 1: L.PrintList(1); //輸出線性表順序表詞頻統(tǒng)計break;case 2: WorLocatMenu(); //順序表順序單詞查找菜單break;case 3:return;default: cout << "輸入的不是有效符號,請重新輸入" << endl; system("pause");} //switch} //whilereturn; }//鏈表順序查找菜單 void LinklistSeqMenu(){LinkList L(WF, sum);while(true){system("cls"); //清屏cout << "*******************基于不同策略的英文單詞的詞頻統(tǒng)計和檢索系統(tǒng)*******************" << endl;cout << "---鏈表順序查找---" << endl;cout << "1.詞頻統(tǒng)計" << endl;cout << "2.單詞查找" << endl;cout << "3.返回上一級" << endl;cout << "請按相應(yīng)的數(shù)字鍵進行選擇:" << endl;int n;cin >> n;switch (n){case 1: L.PrintList(); //輸出線性表鏈表詞頻統(tǒng)計break;case 2:LinklistLocateMenu(); //鏈表單詞查找break;case 3: return;default:cout << "輸入的不是有效符號,請重新輸入" << endl; system("pause"); //暫停} //switch} //whilereturn; }//順序表順序單詞查找菜單 void WorLocatMenu(){SeqList L(WF , sum); system("cls"); //清屏cout << "*******************基于不同策略的英文單詞的詞頻統(tǒng)計和檢索系統(tǒng)*******************" << endl;cout << "---順序表單詞查找---" << endl;cout << "請輸入要查找的單詞:";string word;cin >> word; //鍵盤錄入要查找單詞auto start = system_clock::now(); //開始時間int i = L.SeqlistLocate(word); //返回下標duration<double> diff = system_clock::now() - start; //現(xiàn)在時間 - 開始時間if (i+1) {cout << "此單詞為:" << L.getword(i) << endl;cout << "此單詞的詞頻:" << L.getfre(i) << endl;cout << "查找該單詞所花費的時間:" << (diff.count())*1000 << "毫秒" << endl;cout << "平均查找長度:" << (sum + 1) / 2 << endl;} //ifelsecout << "查找失敗" << endl;system("pause"); //暫停 }//鏈表單詞查找菜單 void LinklistLocateMenu(){LinkList L(WF, sum);system("cls"); //清屏cout << "*******************基于不同策略的英文單詞的詞頻統(tǒng)計和檢索系統(tǒng)*******************" << endl;cout << "---鏈表單詞查找---" << endl;cout << "請輸入要查找的單詞:";string word;cin >> word;auto start = system_clock::now(); //開始時間int i = L.Locate(word);duration<double> diff = system_clock::now() - start; //現(xiàn)在時間 - 開始時間if (i) {cout << "此單詞為:" << L.getdata(i).word << endl;cout << "此單詞的詞頻:" << L.getdata(i).frequency << endl;cout << "查找該單詞所花費的時間:" << (diff.count())*1000 << "毫秒" << endl;cout << "平均查找長度:" << (sum + 1) / 2 << endl;} //ifelsecout << "查找失敗" << endl;system("pause"); //暫停 }//順序表折半查找菜單 void HalfSortMenu(){SeqList L(WF, sum);while(true){system("cls"); //清屏cout << "*******************基于不同策略的英文單詞的詞頻統(tǒng)計和檢索系統(tǒng)*******************" << endl;cout << "---基于順序表的折半查找---" << endl;cout << "1.詞頻統(tǒng)計" << endl;cout << "2.單詞查找" << endl;cout << "3.返回上一級" << endl;cout << "請按相應(yīng)的數(shù)字鍵進行選擇:" << endl;int n;cin >> n;switch (n){case 1:L.PrintList(2); //折半查找,輸出break;case 2: HalfdLocateMenu(); //折半查找break;case 3:return; //退出函數(shù)default: cout << "輸入的不是有效符號,請重新輸入" << endl; system("pause"); //暫停} //switch} //while }//順序表折半查找菜單 void HalfdLocateMenu(){SeqList L(WF, sum);system("cls"); //清屏cout << "*******************基于不同策略的英文單詞的詞頻統(tǒng)計和檢索系統(tǒng)*******************" << endl;cout << "---折半單詞查找---" << endl;cout << "請輸入要查找的單詞:";string word;cin >> word;auto start = system_clock::now(); //開始時間L.BinSearch(word);duration<double> diff = system_clock::now() - start; //現(xiàn)在時間 - 開始時間int i = L.BinSearch(word); //返回下標if (i >= 0) {cout << "此單詞為:" << L.getword(i) << endl;cout << "此單詞的詞頻:" << L.getfre(i) << endl;cout << "查找該單詞所花費的時間:" << (diff.count())*1000 << "毫秒" << endl;cout << "平均查找長度:" << double((log(double(sum) + 1) / log(2)) - 1) << endl;} //ifelsecout << "查找失敗" << endl;system("pause"); //暫停 }//開放地址哈希表類 class HashTable{public:HashTable(); //構(gòu)造函數(shù),初始化空散列表~HashTable(){}; //析構(gòu)函數(shù)int Insert(datatype a); //插入int Search(string word); //查找datatype Get(int a);void Print(); //輸出private:int H(int k); //哈希函數(shù)(散列函數(shù))datatype ht[MaxSize]; //散列表 };//構(gòu)造函數(shù) HashTable::HashTable(){for (int i = 0; i < MaxSize; i++){ht[i].key = 0; //關(guān)鍵碼初始化ht[i].word = "";ht[i].frequency = 0; // 0表示該散列單元為空} //for }//哈希函數(shù),除留余數(shù)法 int HashTable::H(int k){return k % MaxSize; }//輸出函數(shù) void HashTable::Print() {system("cls"); //清屏ofstream fout; //文件寫操作 內(nèi)存寫入存儲設(shè)備fout.open("outfile5.txt"); //打開文件fout << "單詞總數(shù)為:" << sum << endl;fout << "詞頻" << "\t" << "單詞" << endl;for (int i = 0; i < sum; i++) {fout << WF[i].frequency << "\t" << WF[i].word << endl;cout << WF[i].frequency << "\t" <<WF[i].word << endl;} //forsystem("pause"); //暫停 }//查找函數(shù) int HashTable::Search(string word){int key = WordTransitionKey(word); //將單詞轉(zhuǎn)化為關(guān)鍵碼int i = H(key); //計算散列地址,設(shè)置比較的起始位置while (ht[i].key != 0){if (ht[i].word == word) return i; //查找成功else i = (i + 1) % MaxSize; //向后探測一個位置} //whilereturn 0; //查找失敗 }//插入函數(shù) int HashTable::Insert(datatype f_word_key){int key = WordTransitionKey(f_word_key.word);//將單詞轉(zhuǎn)化為關(guān)鍵碼int i = H(key); //計算散列地址,設(shè)置比較的起始位置while (ht[i].key != 0){ //尋找空的散列單元i = (i + 1) % MaxSize; //向后探測一個位置} //whileht[i].key = key; //關(guān)鍵碼賦值ht[i].word = f_word_key.word; //單詞賦值ht[i].frequency = f_word_key.frequency; //詞頻賦值return i; //返回插入位置 }//獲取單詞以及頻率 datatype HashTable::Get(int a){return ht[a]; }//鏈地址法哈希表類 class HashTableLink{public:HashTableLink(); //構(gòu)造函數(shù),初始化開散列表~HashTableLink(); //析構(gòu)函數(shù),釋放同義詞子表結(jié)點int Insert(datatype fword); //插入Node* Search(string word); //查找void Print(); //輸出private:int H(int k); //散列函數(shù)Node* ht[MaxSize]; //開散列表 };//構(gòu)造函數(shù) HashTableLink::HashTableLink(){for (int i = 0; i < MaxSize; i++)ht[i] = NULL; //鏈式存儲結(jié)構(gòu)指針置空 }//析構(gòu)函數(shù),釋放空間 HashTableLink :: ~HashTableLink(){Node* p = NULL, * q = NULL;for (int i = 0; i < MaxSize; i++){p = ht[i];q = p; //用來儲存pwhile (p != NULL){ //p非空p = p->next; //p后移delete q; //刪除qq = p;} //while} //for }//除留余數(shù)法-散列函數(shù) int HashTableLink::H(int k){return k % MaxSize; }//輸出到屏幕和文本文件outfile6.txt void HashTableLink::Print() {system("cls"); //清屏ofstream fout; //文件寫操作 內(nèi)存寫入存儲設(shè)備fout.open("outfile6.txt"); //打開文件fout << "單詞總數(shù)為:" << sum << endl;fout << "詞頻" << "\t" << "單詞" << endl;for (int i = 0; i < sum; i++) {fout << WF[i].frequency << "\t" << WF[i].word << endl;cout << WF[i].frequency << "\t" <<WF[i].word << endl;} //forsystem("pause"); //暫停 }//查找函數(shù) Node* HashTableLink::Search(string word){int k = WordTransitionKey(word); //轉(zhuǎn)化為關(guān)鍵碼int j = H(k); //計算散列地址Node* p = ht[j]; //指針p初始化while (p != NULL){ //p非空if (p->data.word == word)return p; //已找到返回指針elsep = p->next; //p后移} //whilereturn nullptr; //未找到返回空指針 }//插入函數(shù)(前插法) int HashTableLink::Insert(datatype fword){int k = WordTransitionKey(fword.word); //轉(zhuǎn)化為關(guān)鍵碼fword.key = k; //給關(guān)鍵碼賦值int j = H(k); //計算散列地址Node* p = Search(fword.word); //調(diào)用查找函數(shù)if (p != nullptr) //p非空,表示該內(nèi)容已經(jīng)插入過了return -1; //已存在元素k,無法插入 else { //p為空,表示該內(nèi)容未插入p = new Node; //生成新節(jié)點p->data.key = fword.key; //關(guān)鍵碼賦值p->data.frequency = fword.frequency; //詞頻賦值p->data.word = fword.word; //單詞賦值p->next = ht[j]; //新節(jié)點插入ht[j]ht[j] = p; //更新節(jié)點return 1; //插入成功標志 } }//哈希表菜單 void HashMenu(){while(true){system("cls"); //清屏cout << "*******************基于不同策略的英文單詞的詞頻統(tǒng)計和檢索系統(tǒng)*******************" << endl;cout << "---哈希表---" << endl;cout << "1.開放地址法哈希查找" << endl;cout << "2.鏈地址法哈希查找" << endl;cout << "3.返回上一級" << endl;cout << "請按相應(yīng)的數(shù)字鍵進行選擇:" << endl;int n;cin >> n;switch (n){case 1 : OpenHashLocate(); //開放地址法哈希查找break;case 2 : LinkHashLocate(); //鏈地址法哈希查找break;case 3 : return; //退出函數(shù)default: cout << "輸入的不是有效符號,請重新輸入" << endl; system("pause");} //switch} //whilereturn; }//開放地址法哈希查找菜單 void OpenHashLocateMenu(){HashTable HT;for (int i = 0; i < sum; i++)HT.Insert(WF[i]); //把數(shù)據(jù)插入到哈希表中double bulkfactor = sum / MaxSize; //裝填因子system("cls"); //清屏cout << "*******************基于不同策略的英文單詞的詞頻統(tǒng)計和檢索系統(tǒng)*******************" << endl;cout << "---開放地址單詞查找---" << endl;cout << "請輸入要查找的單詞:";string word;cin >> word;auto start = system_clock::now(); //開始時間int i = HT.Search(word); //獲取散列地址duration<double> diff = system_clock::now() - start; //現(xiàn)在時間 - 開始時間if (i) {cout << "此單詞為:" << HT.Get(i).word << endl;cout << "此單詞的詞頻:" << HT.Get(i).frequency << endl;cout << "查找該單詞所花費的時間:" << (diff.count())*1000 << "毫秒" << endl;cout << "平均查找長度:" << (1 + 1 / (1 - bulkfactor)) / 2 << endl;} //ifelsecout << "查找失敗" << endl;system("pause"); //暫停 }//開放地址法哈希查找 void OpenHashLocate(){HashTable HT;for (int i = 0; i < sum; i++)HT.Insert(WF[i]); //把數(shù)據(jù)插入到哈希表中while(true){system("cls"); //清屏cout << "*******************基于不同策略的英文單詞的詞頻統(tǒng)計和檢索系統(tǒng)*******************" << endl;cout << "---基于開放地址法的哈希查找---" << endl;cout << "1.詞頻統(tǒng)計" << endl;cout << "2.單詞查找" << endl;cout << "3.返回上一級" << endl;cout << "請按相應(yīng)的數(shù)字鍵進行選擇:" << endl;int n;cin >> n;switch (n){case 1 : HT.Print(); //詞頻統(tǒng)計break;case 2 : OpenHashLocateMenu(); //開放地址法的哈希查找菜單break;case 3 :return;default: cout << "輸入的不是有效符號,請重新輸入" << endl; system("pause"); //暫停} //switch} //while }//鏈地址法哈希查找 void LinkHashLocate(){HashTableLink HT;for (int i = 0; i < sum; i++)HT.Insert(WF[i]); //把數(shù)據(jù)插入到哈希表while(true){system("cls"); //清屏cout << "*******************基于不同策略的英文單詞的詞頻統(tǒng)計和檢索系統(tǒng)*******************" << endl;cout << "---基于鏈地址法的哈希查找---" << endl;cout << "1.詞頻統(tǒng)計" << endl;cout << "2.單詞查找" << endl;cout << "3.返回上一級" << endl;cout << "請按相應(yīng)的數(shù)字鍵進行選擇:" << endl;int n;cin >> n;switch (n){case 1: HT.Print(); //詞頻統(tǒng)計break;case 2:LinkHashWordLocateMenu(); //單詞查找菜單break;case 3: return; //退出函數(shù)default: cout << "輸入的不是有效符號,請重新輸入" << endl; system("pause"); //暫停} //switch} //while }//鏈地址法哈希查找菜單 void LinkHashWordLocateMenu(){HashTableLink HT;for (int i = 0; i < sum; i++)HT.Insert(WF[i]); //把數(shù)據(jù)插入到哈希表double load_factor = sum / MaxSize;//散列表的裝填因子system("cls");cout << "*******************基于不同策略的英文單詞的詞頻統(tǒng)計和檢索系統(tǒng)*******************" << endl;cout << "---鏈地址單詞查找---" << endl;cout << "請輸入要查找的單詞:";string word;cin >> word;auto start = system_clock::now(); //開始時間HT.Search(word);duration<double> diff = system_clock::now() - start; //現(xiàn)在時間 - 開始時間Node* p = HT.Search(word); //返回目標指針if (p != NULL) {cout << "此單詞為:" << p->data.word << endl;cout << "此單詞的詞頻:" << p->data.frequency << endl;cout << "查找該單詞所花費的時間:" << (diff.count())*1000 << "毫秒" << endl;cout << "平均查找長度:" << 1 + (load_factor) / 2 << endl;} //ifelsecout << "查找失敗" << endl;system("pause"); //暫停 }//二叉排序樹類 class BiSortTree{public:BiSortTree(datatype a[], int n); //帶參構(gòu)造函數(shù),對樹初始化~BiSortTree(){ //析構(gòu)函數(shù)Release(root); } BiNode* InsertBST(datatype data){ //函數(shù)重載,插入數(shù)據(jù)域datareturn InsertBST(root, data);} BiNode* SearchBST(string word){ //函數(shù)重載,查找值為word的結(jié)點return SearchBST(root, word);} void printf(); //輸出函數(shù)private:void Release(BiNode* bt); //釋放空間BiNode* InsertBST(BiNode* bt, datatype data); //插入數(shù)據(jù)域dataBiNode* SearchBST(BiNode* bt, string word); //查找值為word的結(jié)點void InOrder(BiNode* bt); //中序遍歷函數(shù)調(diào)用BiNode* root; //二叉排序樹的根指針 };//構(gòu)造函數(shù) BiSortTree::BiSortTree(datatype a[], int n) {root = NULL; //根指針置空for (int i = 0; i < n; i++)root = InsertBST(root, a[i]); //遍歷,插入數(shù)據(jù) }//輸出函數(shù) void BiSortTree::InOrder(BiNode* bt){ //遞歸輸出二叉排序樹ofstream fout; //文件寫操作 內(nèi)存寫入存儲設(shè)備fout.open("outfile4.txt", ios_base::out | ios_base::app); //打開文件并將內(nèi)容追加到文件尾if (bt == NULL) //遞歸調(diào)用的結(jié)束條件,根指針為空return; //退出函數(shù) else{InOrder(bt->lchild); //中序遞歸遍歷bt的左子樹cout << bt->data.frequency << "\t" << bt->data.word << endl; //訪問根結(jié)點bt的數(shù)據(jù)域,輸出到屏幕fout << bt->data.frequency << "\t" << bt->data.word << endl; //訪問根結(jié)點bt的數(shù)據(jù)域,輸出到文件fout.close(); //關(guān)閉文件InOrder(bt->rchild); //中序遞歸遍歷bt的右子樹 } //else }//輸出二叉排序樹到屏幕和outfile4.txt void BiSortTree::printf() {system("cls"); //清屏ofstream fout; //文件寫操作 內(nèi)存寫入存儲設(shè)備fout.open("outfile4.txt");//打開文件fout << "單詞總數(shù)為:" << sum << endl;fout << "詞頻" << "\t" << "單詞" << endl;InOrder(root); //輸出函數(shù)system("pause"); //暫停return; //退出函數(shù) }//遞歸查找函數(shù),返回指針 BiNode* BiSortTree::SearchBST(BiNode* bt, string word){if (bt == NULL) return NULL; //未找到,返回NULLif (bt->data.word == word) return bt; //找到word,返回該指針else if (bt->data.word > word) //數(shù)據(jù)大于wordreturn SearchBST(bt->lchild, word); //遞歸查找左子樹else //數(shù)據(jù)小于wordreturn SearchBST(bt->rchild, word); //遞歸查找右子樹 }//遞歸插入函數(shù) BiNode* BiSortTree::InsertBST(BiNode* bt, datatype data){if (bt == NULL){ //找到插入位置BiNode* s = new BiNode; //生成一個新的儲存空間s->data = data; //為數(shù)據(jù)域賦值s->lchild = NULL; //左孩子指針置空s->rchild = NULL; //右孩子指針置空bt = s; //根指針更新return bt; //返回根指針} //ifelse if (WordTransition(bt->data.word) > WordTransition(data.word)){ //根節(jié)點數(shù)據(jù)大于要插入的數(shù)據(jù)bt->lchild = InsertBST(bt->lchild, data); //更新左孩子指針return bt; //返回根指針} //else ifelse{ //根節(jié)點數(shù)據(jù)小于要插入的數(shù)據(jù)bt->rchild = InsertBST(bt->rchild, data); //更新有孩子指針return bt; //返回根指針} //else }//遞歸析構(gòu)函數(shù) void BiSortTree::Release(BiNode* bt){if (bt == NULL)return; //根指針為空直接退出else {Release(bt->lchild); //釋放左子樹Release(bt->rchild); //釋放右子樹delete bt; //釋放根結(jié)點} }// 二叉排序樹菜單 void BiTreeMenu(){while(true){system("cls"); //清屏cout << "*******************基于不同策略的英文單詞的詞頻統(tǒng)計和檢索系統(tǒng)*******************" << endl;cout << "---二叉排序樹查找---" << endl;cout << "1.二叉排序樹的順序查找" << endl;cout << "2.返回上一級" << endl;cout << "請按相應(yīng)的數(shù)字鍵進行選擇:" << endl;int n;cin >> n;switch (n){case 1: BitreeLocateMenu(); //二叉排序樹查找菜單break; //退出switchcase 2: return; //退出函數(shù)default:cout << "輸入的不是有效符號,請重新輸入" << endl; system("pause"); //暫停} //switch} //while }//二叉排序樹的順序查找菜單 void BitreeLocateMenu(){BiSortTree B(WF,sum);while(true){system("cls"); //清屏cout << "*******************基于不同策略的英文單詞的詞頻統(tǒng)計和檢索系統(tǒng)*******************" << endl;cout << "---基于二叉排序樹的順序查找---" << endl;cout << "1.詞頻統(tǒng)計" << endl;cout << "2.單詞查找" << endl;cout << "3.返回上一級" << endl;cout << "請按相應(yīng)的數(shù)字鍵進行選擇:" << endl;int n;cin >> n;switch (n){case 1: B.printf(); break;case 2: BitreeWordLocMenu(); //二叉排序樹查找單詞菜單break;case 3:return; //退出函數(shù)default: cout << "輸入的不是有效符號,請重新輸入" << endl; system("pause"); //暫停} //switch} //while }//二叉排序樹查找單詞菜單 void BitreeWordLocMenu(){BiSortTree B(WF,sum);system("cls"); //清屏cout << "*******************基于不同策略的英文單詞的詞頻統(tǒng)計和檢索系統(tǒng)*******************" << endl;cout << "---二叉排序單詞查找---" << endl;cout << "請輸入要查找的單詞:";string word;cin >> word;auto start = system_clock::now(); //開始時間B.SearchBST(word);duration<double> diff = system_clock::now() - start; //現(xiàn)在時間 - 開始時間BiNode* p = NULL; //指針置空p = B.SearchBST(word);if (p != NULL) {cout << "此單詞為:" << p->data.word << endl;cout << "此單詞的詞頻:" << p->data.frequency << endl;cout << "查找該單詞所花費的時間:" << (diff.count())*1000 << "毫秒" << endl;cout << "平均查找長度:" << sum << endl;} //ifelsecout << "查找失敗" << endl;system("pause"); //暫停 }

    六、運行結(jié)果

    這里通過查找同一個單詞來分辨不同查找方式的效率









    七、總結(jié)

    通過這次實驗,讓我對順序表、鏈表、二叉排序樹、連地址哈希表和開放地址哈希表的結(jié)構(gòu)有了更深刻的認識;學會如何去使用基于以上結(jié)構(gòu)的順序查找、折半查找等;還學會了如何輸出查找時間以及他們的ASL(平均查找長度)

    總結(jié)

    以上是生活随笔為你收集整理的数据结构 C++实现 基于不同策略的英文单词的词频统计和检索系统(糅合版)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。