主体VSM_SetUP.cpp;
1 /*[ar:歌词作者] 2 [ti:歌词(歌曲)的标题] 3 */ 4 //编写程序实现lrc(歌词) 文件的检索,检索模型要求采用向量空间模型。请将源程序和文档压缩后,一并上传。 5 #include<iostream> 6 7 #include"Document_Index.h" 8 9 using namespace std; 10 void main() { 11 cout << "*****本程序实现一个向量空间模型,对(D:\暂时的)文件夹下的lrc文件进行遍历建立一个对应于歌曲名,作曲者,歌词主体的检索系统,请根据需要进行查询*****" << endl << endl; 12 cout << "*****检索出的文档编号对应的文档名字请在(检索结果.txt)内查找*****" << endl; 13 string query; 14 int select,result; 15 int isornot = 2; 16 Doc_Analysis doc_analysis; 17 doc_analysis.SETUP_Index(); 18 ReQuery getResult(&doc_analysis); 19 20 while (isornot>=1) { 21 cout << "输入查询词项:"; 22 if (isornot != 2) { 23 getline(cin, query); 24 } 25 getline(cin, query); 26 27 cout << "请选择查询模式(1为查歌曲,2为查歌手,3为查歌词主体):"; 28 cin >> select; 29 cout << "请选择返回结果的数量:"; 30 cin >> result; 31 getResult.Query(query, result, select); 32 cout << "is or not(1表示继续查询,0表示退出查询) ? " ; 33 cin >> isornot; 34 } 35 }
类的保存文件内:Document_Index.cpp和Document_Index.h
1 #pragma once 2 #include<iostream> 3 #include<fstream> 4 #include<vector> 5 #include<math.h> 6 #include<string> 7 #include<iomanip> 8 #include <stdio.h> 9 #include<io.h> 10 #include <windows.h> 11 using namespace std; 12 13 const static int Maxsize = 10000; 14 const static int maxsize = 100;//a line and a smalllist 15 16 //得分和相应的文档编号 17 struct ScoreandDoc { 18 float score; 19 int text_number; 20 }; 21 22 //包含词的所在的文档编号,词项在此文档出现的频率tf 23 struct Word_Doc { 24 int text_number; 25 int text_fre; 26 }; 27 28 //设计保存词项倒排记录头部的一个结构 29 struct Index_List {//存储每个词的头项,包含单词和指向倒排记录的指针,存储df,df是包含词项的文档的数目,同时也是倒排记录的长度。next指向下一个词项 30 float df; 31 string word; 32 vector<Word_Doc> head_docID;// = nullptr; 33 Index_List * next = nullptr; 34 }; 35 36 //文档检索类,VSM的主体 37 class Doc_Analysis { 38 39 string BTEMP[Maxsize]; 40 string TEMP[maxsize]; 41 int arsize;// 42 int tisize; 43 Index_List * arofMusic_idList; //歌曲作者索引的链表头 44 Index_List * tiofMusic_idList; //歌曲名字索引的链表头 45 Index_List * idList; //主体歌词倒排索引的链表头 46 int size; //文档的词项的数目,即文档长度 47 int allsize;//总的词数 48 int N; //歌词主体文档集的大小,共有N篇文档 49 int sizeofmusicname; //歌词名字和歌词作者的大小 50 string Inp_Temp_Lyrics[Maxsize]; //存放歌词主体 51 string ti_Temp[maxsize/5];//歌曲名称和歌曲作者的暂时存放之地 52 string ar_Temp[maxsize / 5];//歌曲名称和歌曲作者的暂时存放之地 53 public: 54 Doc_Analysis() { 55 size = 0; 56 allsize = 0; 57 arsize = 0; 58 tisize = 0; 59 N = 0; 60 idList = nullptr; 61 arofMusic_idList = nullptr; 62 tiofMusic_idList = nullptr; 63 }; 64 ~Doc_Analysis() { 65 66 }; 67 68 69 //把从文档中检索的词插入Inp_Temp_Words[Maxsize],如果不在就直接插入,如果已经存在则加一个 70 71 //打开文件输入歌词,对词项进行分析,把歌曲的作者和歌曲名取出,存入对应的倒排索引,但是这个索引很小,所以可以直接构建倒排索引表。参数分别为:文件名,文档的编号。先对文档内歌词的作者和调用分离出的词项最终存储在Inp_Temp_Words[Maxsize],返回文档的词数 72 int Doc_input(string filename, int number); 73 74 //被int Doc_input(string filename, int number);调用,将分离出的词项存储在temp_Words[]中,size表示其大小,j表示其从哪一个数开始放入 75 int Temp_Insert(string temp_words[],char T[],int &size); 76 77 //对此文档的词项的表进行归并排序(按字典序) 78 void Doc_mergesort(string *inputWord, string* Temp, int left, int right); 79 80 //将此次输入的文档分词排序后得到的词项表存入最终的倒排索引中 81 Index_List* insert_IndexList(string *inputWord, int n,int NofDoc, Index_List * idList); 82 83 //歌曲名,作者,歌词主体倒排索引总体构建 84 void SETUP_Index();// {}; 85 86 //返回最终查询的文档集大小 87 int SizeOfDocSet() { 88 return N; 89 } 90 91 //返回最终生成的歌词主体倒排索引表 92 Index_List* tiIndex_head() { 93 return tiofMusic_idList; 94 }; 95 96 //返回最终生成的歌ming倒排索引表 97 Index_List* DocIndex_head() { 98 return idList; 99 }; 100 101 //返回最终生成的作者倒排索引表 102 Index_List* arIndex_head() { 103 return arofMusic_idList; 104 }; 105 106 //此函数实现寻找指定文件夹下的指定后缀文件,并且保存其完整的路径 107 void GetAllFormatFiles(string path, vector<string>& files, string format); 108 // 109 }; 110 111 //对输入的查询词项进行分析,返回输入结果 112 class ReQuery { 113 Doc_Analysis* LMA;//歌词倒排索引的链表头 114 float *Scores;//每个查询词项的初始得分 115 float *arLength;//每个文档的长度 116 float *tiLength; 117 float *Length; 118 int N;//文档集大小 119 public: 120 ReQuery(Doc_Analysis* TEMP) {//得到Doc_Analysis返回的文档集长度和链表头 121 N = TEMP->SizeOfDocSet(); 122 Scores = new float[N]; 123 Length = new float[N]; 124 125 LMA = TEMP; 126 for (int i = 0; i < N; i++) { 127 Scores[i] = 0; 128 Length[i] = 0; 129 } 130 }; 131 ~ReQuery() { 132 delete[] Scores; 133 delete[] Length; 134 delete[] arLength; 135 delete[] tiLength; 136 }; 137 138 //查询所有词项,对所有倒排索引表遍历一次,将每个向量的长度计算出来,初始化得分数组 139 void initialLength(Index_List * idList, float *tempLength); 140 141 //输入查询歌词词项,输出查询结果,返回排名前k的文档编号,select 为选择的查询模式,1为查歌名,2为查歌手,3为查歌词主体 142 bool Query(string query, int k,int select=1); 143 144 //查询某一个词是否在其中,有则返回其df,无则返回0 145 int isInner(string elem, Index_List idList[],Index_List &nowTemp); 146 147 //某个词项对于suoyou文档的得分 148 float ScoreofaDoc(Index_List *idList, Index_List* word, int iQ); 149 150 //进行堆排序,将所有的得分进行排序 151 bool HeapSort(float Scores[], int n,int k); 152 153 }; 154 155 //堆排序,建立最大堆 156 class Max_Heap { 157 ScoreandDoc *Heap; 158 int size; 159 int n; 160 void siftdown(int elem); 161 public: 162 Max_Heap(int num, int max, ScoreandDoc *temp) { 163 n = num; 164 size = max; 165 Heap = temp; 166 buildHeap(); 167 }; 168 void buildHeap() { 169 for (int i = n / 2 - 1; i >= 0; i--) 170 siftdown(i); 171 }; 172 int heapsize()const { 173 return n; 174 } 175 bool isLeaf(int pos)const { 176 return (pos >= n / 2) && (pos < n); 177 } 178 int leftchild(int pos)const { 179 return 2 * pos + 1; 180 } 181 int rightchild(int pos)const { 182 return 2 * pos + 2; 183 } 184 ScoreandDoc removemax(float it); 185 186 };
——————————————————————————————————————————————————————————————————————————————————
1 #pragma once 2 #include"Document_Index.h" 3 #include<iostream> 4 #include<fstream> 5 #include<vector> 6 #include<math.h> 7 #include<string> 8 #include<iomanip> 9 #include <stdio.h> 10 #include<io.h> 11 #include <windows.h> 12 using namespace std; 13 14 ///////////类:Doc_Analysis/////////////////////// 15 16 //打开文件输入歌词,对词项进行分析,把歌曲的作者和歌曲名取出,存入对应的倒排索引,但是这个索引很小,所以可以直接构建倒排索引表。参数分别为:文件名,文档的编号。调用分离出的词项最终存储在Inp_Temp_Words[Maxsize],返回歌词文档的词数 17 int Doc_Analysis::Doc_input(string filename, int number) { 18 ifstream fin(filename); 19 if (!fin.is_open()) { 20 exit(0); 21 } 22 N++; 23 // cout << "此文件夹文档数目:" << N << endl; 24 char c[maxsize] = { '