STL MAP及字典树在关键字统计中的性能分析
转载请注明出处:http://blog.csdn.net/mxway/article/details/21321541
在搜索引擎在通常会对关键字出现的次数进行统计,这篇文章分析下使用C++ STL中的map进行统计,及使用字典树进行统计在运行速度,空间及适用场合进行分析。首先随机生成100万个3-6长度的字符串。为了简化问题,字符串中仅由小写字母组成。另外随机生成10万个长度3-8的字符串用于测试map和字典树在查询方面的效率。
下面是使用map和字典树实现的C++代码:
STL map实现统计的源码:
#include<iostream> #include<ctime> #include<fstream> #include<string> #include<map> using namespace std; int main() { clock_t start,end; map<string,int> dict; string word; ifstream in("data.dat"); start = clock(); while(in>>word) { if(dict[word]) { dict[word] = 1; } else { dict[word]++; } } in.close(); end = clock(); cout<<"STL MAP统计花费的时间为:"<<end-start<<"毫秒"<<endl; map<string,int>::iterator itr = dict.begin(); start = clock(); ofstream out("out.txt"); while(itr != dict.end() ) { out<<itr->first<<" "<<itr->second<<endl; itr++; } end = clock(); cout<<"STL MAP输出到文件花费时间为:"<<end-start<<"毫秒"<<endl; out.close(); start = clock(); int sum1=0,sum2=0; ifstream searchIn("search.dat"); while(searchIn>>word) { if(dict[word] != 0) { sum1++; } else { sum2++; } } end = clock(); cout<<"找到单词:"<<sum1<<"-->"<<"没有找到单词:"<<sum2<<endl; cout<<"查询花费时间:"<<end-start<<endl; return 0; }
字典树实现代码:
#include<iostream> #include<string.h> #include<fstream> #include<ctime> using namespace std; char str[20];//用于在输出字典树中的单词时使用。 struct Node { int cnt; struct Node *child[26]; Node() { int i; for(i=0; i<26; i++) { child[i] = NULL; } cnt = 0; } }; /* * * 将一个字符串插入到字典树中 * */ void Insert(Node *root, char word[]) { Node *p = root; int i,index; int len = strlen(word); for(i=0; i<len; i++) { index = word[i] - 'a';//这里是一个hash算法,只考虑小写字母的情况 if(p->child[index] == NULL) { p->child[index] = new Node(); } p = p->child[index]; } p->cnt++;//单词数加1。 } /* * * 字符串输出到文件 */ void OutToFile(char *word,int cnt) { ofstream out("out.txt",ios::app); out<<word<<" "<<cnt<<endl; out.close(); } /* *将字典树中的单词及其出现次数输出 * */ void OutputWord(Node *p,int length) { int i; if(p->cnt != 0)//找到了一个字符串 { str[length] = '\0'; OutToFile(str,p->cnt); } for(i=0; i<26; i++) { if(p->child[i] != NULL) { str[length] = i+'a';//根据下标还原字符 OutputWord(p->child[i],length+1); } } } /** * 查询word是否在字典树中 * */ int SearchWord(Node *p,char word[]) { int i,index; int len = strlen(word); for(i=0; i<len; i++) { index = word[i]-'a'; if(p->child[index] == NULL)//没有找到 { return 0; } p = p->child[index]; } if(p->cnt > 0) { return 1;//找到 } else//前缀字符串不能算是有这个单词 { return 0; } } /* * *销毁字典树 * */ void DestroyTrieTree(Node *p) { int i; for(i=0; i<26; i++) { if(p->child[i] != NULL) { DestroyTrieTree(p->child[i]); } } delete p; } int main() { Node *Root = new Node(); char word[20]; clock_t start,end; start = clock(); ifstream in("data.dat"); while(in>>word) { Insert(Root,word); } end = clock(); cout<<"使用字典树进行统计花费时间:"<<end-start<<"毫秒"<<endl; start = clock(); OutputWord(Root,0); end = clock(); cout<<"输出到文件花费时间:"<<end-start<<"毫秒"<<endl; in.close(); int sum1=0,sum2=0; start = clock(); ifstream searchIn("search.dat"); while(searchIn>>word)// { if(SearchWord(Root,word) ) { sum1++; } else { sum2++; } } searchIn.close(); end = clock(); cout<<"找到单词:"<<sum1<<"-->"<<"没有找到单词:"<<sum2<<endl; cout<<"查询花费时间:"<<end-start<<endl; /** 销毁字典树 */ for(int i=0; i<26; i++) { if(Root->child[i] != NULL) { DestroyTrieTree(Root->child[i]);//销毁字典树 } } return 0; }
下面是两个程序在release版本下的运行情况:
一、运行时间方面:从上面可以看出在统计和查询过程中使用字典树的速度明显优于map。假设字符串长度为n,共有m个关键字。由于map其底层是由红黑树(红黑树本质一种排序二叉树)支持,所以将一个字符串插入到map中需要log(m)次才能找到其所在位置。在这log(m)次中每次极端情况下需要进行n次比较。所以往map中插入一个字符串需要O(n*log(m))的时间复杂度。对于字典树从上面的程序中可以看出。插入一个字符串只与字符串的长度有关而与关键字的个数无关,其时间复杂度为O(n)。而在将所有的关键字及其出现次数写到外部文件时,字典树花费了巨大的时间。这是由于字典树的遍历是递归的,大量的时间花在了栈的建立和销毁上。
二、在内存空间使用方面
以插入一个字符串a为例,插入到字典树中正真存储有用的数据只占一个空间,另外需要26个空间的指针域。而插入到map,其底层是红黑树,数据占用一个空间;另外再需两个空间的指针指向其左右孩子。所以在空间使用方面,map使用较少的内存空间。
三、适用场合
(1)字典树及map的比较:1.字典树在插入和查询一个的字符串的的时间较map快。2.map比字典树使用更少的内存空间。3.在需要在统计的数据写到外部文件时,map比字典树快很多。
(2)字典树的适用场合:
在不需要将字典树的数据写到外部文件的情况,并对内存空间没有太多要求以及对系统响应要求较高的系统中使用字典树优于map。比如在12306网站的订票页面,在出发地框中输入bj就会提示“北京”等信息。
在对系统响应要求不高而对内存有限制的系统,以及需要将内存中存储的数据写到外部文件的系统使用map优于字典树。
STL MAP及字典树在关键字统计中的性能分析的更多相关文章
- POJ 2503 Babelfish(map,字典树,快排+二分,hash)
题意:先构造一个词典,然后输入外文单词,输出相应的英语单词. 这道题有4种方法可以做: 1.map 2.字典树 3.快排+二分 4.hash表 参考博客:[解题报告]POJ_2503 字典树,MAP ...
- 51nod 1095 Anigram单词【hash/map/排序/字典树】
1095 Anigram单词 基准时间限制:1 秒 空间限制:131072 KB 分值: 10 难度:2级算法题 收藏 关注 一个单词a如果通过交换单词中字母的顺序可以得到另外的单词b,那么定义b ...
- (字典树模板)统计难题--hdu--1251
链接: http://acm.hdu.edu.cn/showproblem.php?pid=1251 在自己敲了一遍后终于懂了,这不就用了链表的知识来建立了树,对!就是这样的,然后再查找 代码: #i ...
- 字典树 HDU 1251 统计难题
;} 之前写的#include<iostream> #include<algorithm> #include<stdio.h> using namespace st ...
- poj 1204 Word Puzzles(字典树)
题目链接:http://poj.org/problem?id=1204 思路分析:由于题目数据较弱,使用暴力搜索:对于所有查找的单词建立一棵字典树,在图中的每个坐标,往8个方向搜索查找即可: 需要注意 ...
- 算法学习笔记(一)C++排序函数、映射技巧与字典树
1.头文件algorithm中有函数sort()用于排序,参数为:排序起始地址,排序结束地址,排序规则(返回bool型)例如,要将array[] = {5,7,1,2,9}升序排列,则使用: bool ...
- poj2513--并查集+欧拉路+字典树
经典好题,自己不知道哪里错了交上去是RE,可能是数组开的不好吧,字典树老碰到这种问题.. 先马上别人的代码,有空对拍看看 #include <cstdio> #include <cs ...
- hdu2609 How many 字典树+最小表示法
Give you n ( n < 10000) necklaces ,the length of necklace will not large than 100,tell meHow many ...
- HDOJ/HDU 1251 统计难题(字典树啥的~Map水过)
Problem Description Ignatius最近遇到一个难题,老师交给他很多单词(只有小写字母组成,不会有重复的单词出现),现在老师要他统计出以某个字符串为前缀的单词数量(单词本身也是自己 ...
随机推荐
- fpm来制作rpm包
转自 http://blog.halfss.com/blog/2013/02/26/fpmbao-guan-li/ 另查看 http://my.oschina.net/lxcong/blog/1438 ...
- c# 访问ftp
ftp从服务器上获取通信设备吐出的mr数据,该方案估计在通信行业上一个很普遍的一种方案,很奇怪为什么不把这些数据直接存储到数据库中呢,比如hadoop,反而还需要第三方搞网优的软件开发人员从ftp上读 ...
- leetcode143- Reorder List问题
题目要求: Given a singly linked list L: L0→L1→…→Ln-1→Ln, reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→… You m ...
- iOS 延迟执行
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(<#delayInSeconds#> * NSEC_PER_SEC)), ...
- ASP.NET的一般处理程序对数据的基本操作
TableList.ashx: <%@ WebHandler Language="C#" Class="TableList" %> using Sy ...
- [原创]java WEB学习笔记80:Hibernate学习之路--- hibernate配置文件:JDBC 连接属性,C3P0 数据库连接池属性等
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- Ejb: remote调用
用的是wildfly 9.0.2 一:在myeclipse中新建wildfly 9.0.2的server(如何新建去网上搜) 二:修改wildfly server的argument(在run conf ...
- sql字符转换函数大全
删除空格 有两个函数,TTRIM()和LTRIM(),可以用来从字符串中剪掉空格.函数LTRIM()去除应该字符串前面的所有空格:函数RTRIM()去除一个字符串尾部的所有空格.这些和vbscript ...
- CSS3 Transform Matrix
css3中的transform让我们操作变形变得很简单,诸如,translate–移动,scale–缩放,rotate–旋转,skew–斜切.这几个属性很方便,也很简单,但是其中matrix我们就不常 ...
- 不同版本mysql语句不兼容原因
一般是sql_mode不相同,可以认为规则不一致.(语法的变化非常小,一般可以忽略) 如果想要导入不同版本的数据.可以: 手动处理一些导入错误或者采用其他的办法. 或者 修改sql_mode.具体修改 ...