1.算法介绍
这个程序的功能是:随机生成一个词典,10w左右的词,每个词是10~30的英文字母串,实现词典查找算法,即给定任意一个字符串,去看在词典中是否存在
整体的思路是:
(1)字符串生成函数。该函数能够生成长度在10~30之间的字符串,字符串的长度是随机的,字符也都是随机的。
(2)生成10w个字符串,将字符串写入文件。
(3)读取刚才生成的词典文件,将其中的字符串读出,每个字符串作为一个词条。词典用vector来存储。
(4)对词典中的词条进行排序,按照字母表的顺序进行存储。排序使用快速排序算法,其中快速排序的枢轴选择上选用首、尾、中间三个数的之间置,并且在递归到规模比较小的时候使用插入排序,以减少递归过程不断创建函数的开销。
(5)在排好序的词典中查找目标字符串。字符串查找采用二分查找法。
(6)将排序和查找过程用C++标准库中的sort()和find()函数实现,观察我的函数和标准库中的函数的性能。
2.时间复杂度分析
快速排序的时间复杂度为nlogn,二分查找的时间复杂度为logn。通过与标准库中的函数进行对比,发现自己写的函数同标准库中的函数性能上有差距。
3.源代码
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib> //函数srand()
#include <ctime> //函数time()
#include <vector>
#include <sys/time.h>
#include <algorithm>
using namespace std;
const long LEN = 100000; //词典的规模
const int MAX = 30; //词条的最大长度
const int MIN = 10; //词条的最小长度
int limit_value = 25; //进行插入排序的阈值
//生成随机字符串
string rand_string(int min, int max){
char a[MAX+1];
int len = rand()%(max - min) + min;
for(int i = 0; i < len; i++){
a[i] = rand()%26 + 'a';
}
a[len] = '\0';
string str(a);
return str;
}
//将字符串写入文件,构建词典
void write_dict(){
ofstream fout;
fout.open("dict.txt");
srand((unsigned)time(NULL));
for(int i = 0; i < LEN; i++){
string str = rand_string(10, 30);
fout << str << '\n';
fout << flush;
}
fout.close();
}
//从文件中读取词典信息
vector<string> read_dict(){
ifstream fin;
fin.open("dict.txt");
string textline;
vector<string> dict;
while(getline(fin, textline, '\n')){
dict.push_back(textline);
}
return dict;
}
//比较函数,用于比较两个字符串的相对大小
int compare(string &x, string &y){
int xlen = x.size();
int ylen = y.size();
int i = 0;
while(i < xlen && i < ylen){
if(x[i] == y[i]){
i++;
}else if(x[i] > y[i]){
return 1;
}else{
return -1;
}
}
if(xlen == ylen){
return 0;
}
if(i == xlen){
return -1;
}
if(i == ylen){
return 1;
}
}
//对原始词典中的词进行排序,建立新的词典,新词典顺序排列
//插入排序
void insert_sort(vector<string> &dict, int low, int high){
for(int i = low + 1; i <= high; i++){
string tmp = dict[i];
for(int j = i - 1; j >= low; j--){
if(compare(tmp, dict[j]) < 0){
dict[j+1] = dict[j];
}else{
dict[j+1] = tmp;
break;
}
}
}
}
//枢轴元素的选取,三者取中
void select_PivotMid(vector<string> &dict, int low, int high){
int mid = low + ((high - low) >> 1);
if(compare(dict[mid], dict[high])){
swap(dict[mid], dict[high]);
}
if(compare(dict[low], dict[high])){
swap(dict[low], dict[high]);
}
if(compare(dict[mid], dict[low])){
swap(dict[mid], dict[high]);
}
}
//快速排序,其中枢轴是三者取中,到一定程度用插入排序
void quick_sort(vector<string> &dict, int low, int high){
if(low < high){
if(high - low < limit_value){
insert_sort(dict, low, high);
}else{
select_PivotMid(dict, low, high);
string pivot = dict[low];
int i = low, j = high;
while(i < j){
while(i < j && compare(dict[j], pivot) > 0){
j--;
}
if(i < j){
dict[i] = dict[j];
i++;
}
while(i < j && compare(dict[i], pivot) < 0){
i++;
}
if(i < j){
dict[j] = dict[i];
j--;
}
}
dict[i] = pivot;
quick_sort(dict, low, i - 1);
quick_sort(dict, i + 1, high);
}
}
}
//验证排序是否正确
int verify(vector<string> &dict){
for(int i = 0; i < dict.size() - 1; i++){
if(dict[i] > dict[i+1]){
cout << i << endl;
return -1;
}
}
return 0;
}
//二分搜索,在字典中搜索目标字符串是否存在
int binary_search(string &str, vector<string> dict){
int low = 0;
int high = dict.size();
int pos = 0;
while(low <= high){
int mid = (low + high)/2;
int flag = compare(dict[mid], str);
if(flag == 0){
return mid;
}else if(flag > 0){
high = mid - 1;
}else{
low = mid + 1;
}
}
return -1;
}
long getCurrentTime(){
struct timeval tv;
gettimeofday(&tv, NULL);
return tv.tv_sec*1000 + tv.tv_usec/1000;
}
int main(){
//string a = rand_string(MIN,MAX);
string a = "siubetamwm";
//1.1读取数据
vector<string> dict = read_dict();
cout << "我的算法:" << endl;
//1.2排序
long time_1 = getCurrentTime();
quick_sort(dict, 0, dict.size()-1);
long time_2 = getCurrentTime();
int isTrue = verify(dict);
cout << " 排序结果:" << ((isTrue >= 0) ? "Yes" : "No") << endl;
//1.3搜索
long time_3 = getCurrentTime();
int isFind = binary_search(a, dict);
cout << " 搜索结果:" << ((isFind >= 0) ? "Yes" : "NO") << endl;
long time_4 = getCurrentTime();
cout << "模板算法:" << endl;
//2.1读取数据
vector<string> dict_2 = read_dict();
//2.2排序
long time_5 = getCurrentTime();
sort(dict_2.begin(), dict_2.end());
long time_6 = getCurrentTime();
int isTrue_2 = verify(dict_2);
cout << " 排序结果:" << ((isTrue_2 >= 0) ? "Yes" : "No") << endl;
//2.3搜索
long time_7 = getCurrentTime();
vector<string>::iterator s = find(dict_2.begin(), dict_2.end(), a);
int isFind_2 = -2;
if(s != dict_2.end()){
isFind_2 = 0;
}else{
isFind_2 = -1;
}
cout << " 搜索结果:" << ((isFind_2 >=0) ? "Yes" : "No") << endl;
long time_8 = getCurrentTime();
cout << endl;
cout << "我的算法:" << endl;
cout << " 排序时间:" << time_2 - time_1 << endl;
cout << " 搜索时间: " << time_4 - time_3 << endl;
cout << "模板算法:" << endl;
cout << " 排序时间:" << time_6 - time_5 << endl;
cout << " 搜索时间:" << time_8 - time_7 << endl;
}