如题,我要找一个效率比较高的方法,欢迎大家来讨论。如果答案是暴力扫最快的话,我自扇耳光三百下!
一个含有1亿个QQ号码的文件,面对这种大数据处理,还要满足最快查找到QQ的需求,如果是我,我会先从这几方面考虑。
一、硬件配置
二、编程语言
三、算法
四、查前判断
五、存储区域
-------------------------------且听我慢慢道来---------------------------
一、硬件配置——命令行下运行的最快的计算机
想快点查找,兵器必须要好,那么就得做到以下几点:
1. 操作系统
放弃图形用户界面用命令行界面的操作系统,不解释。如果Windows和Linux之间,貌似只得选Linux了。
2. 采用世界上最快的计算机
国产的天河二号超级计算机,Cray超级计算机,、量子计算机,生物计算机,哪个最快就用哪个吧。
3.世界上最快的计算机构成的服务器集群来最优共同合作处理。
二、编程语言——尽量接近底层的编程语言
高级语言貌似总是没有低级语言的处理速度快,因此应该尽量使用接近底层的编程语言。
三、算法——操作系统分页原理+时间复杂度最低的算法
题目中只求查询速度快即可,那么意思是不是只要时间复杂度低点,多牺牲点空间似乎也无所谓。
始终觉得操作系统的分页查询原理很不错,在此基础上再使用一种时间复杂度最低的算法,那么速度应该会提高不少。
四、查前判断
1.查询前先判断QQ位数
查询之前,先判断QQ位数,可缩小一部分分页查询范围。
2.逐位位数分页判断
从最高位开始判断每一位都进行判断,该位属于从哪一页,哪个表。
五、存储区域——构造高速缓冲区
尽量存储到一个存取速度比较快的数据结构内,并放到存取速度最快的存储区内,位数判断后将满足的页加载到内存。
异想天开班门弄斧胡言乱语一番,梦中不知所云。
导入数据库
select.......
你给的QQ号码是不是基本有序的, 这个的看你给的序列来选择相应的查找算法吧
先把这1亿个QQ排序下,再用2分法查找
如果QQ号是按照一定顺序排列的话,折半查找应该是最快的。如果不是按顺序排列的话,我认为还是并行查找比较快,即从头和尾同时查找。
居然不能只打3个字,10叉树
struct node{
int a;
int flag;
long pos;
struct node *next[10];
struct node *father;
};
一个字符一个字符读,每个字符一个节点,判断下该字符节点是否存在,不存在动态创建个,遇到空格前面那个字符对应的节点flag赋值1
ftell得到位置,复制到节点的pos中,然后不断读啊写啊
最后构成了一个好大的树
最后查的时候循环遍历下去就行了吧
一亿个数据,内存可够用都不考虑一下。
最简单的办法就是字典树。查找效率为Log(N)
个人认为,你如果查多次,可以先对数据进行处理;但只查一次,想准确只有遍历,想快速,牺牲准确性吧
使用比较底层的编程语言
多线程
算法,优化
有条件的话分布式计算
如果平台支持,还可以用平台提供的的接口,比如在Windows系统,可以内存映射文件,当然最好能编写驱动程序,在驱动程序中直接控制磁盘设备,避免了在应用层调用API,中断进内核,系统服务例程,I/O管理,缓冲区复制,过滤设备等等的影响读取速度
取决于你的数据类型:
要是qq号以整型的方式保存在数据库,那么完全可以通过数值查找;
如果是字符型,可以通过双重遍历:(算法用python实现为)
index = 0
7 current_src = []
8
9 """itering the dst_qqs"""
10 for dst_qq in dst_qqs:
11 print 'match -->',dst_qq,'in ',index
12 for src_qq in src_qqs:
13 if src_qq[index]==dst_qq:
14 current_src.append(src_qq)
15 print 'match:',src_qq
16 else:
17 print 'not match:',src_qq
18
19 time.sleep(1)
20 index += 1
21 src_qqs = current_src
原理:先遍历目标qq号,每次获取一位,并且内部遍历目标qq源,进行比对每一组qq的对应位,符合添加到列表中;
此时,设1亿位qq号中,0~9对应每一位的概率相同,则选出1000万组qq号;
继续遍历:(设目标qq号为9位)则遍历外部遍历9次,内部遍历依次为:
10000万 (即1亿)
1000万
100万
10万
1万
1000
100
10
1
时间复杂度可以自行演算;
建议使用数据挖掘的思想做一下,对数据进行预处理,分块分片处理,感觉会解决数据大,内存不够的问题
根据你的号码序列来选择不同的方法,有序就是折半,无序就是并行
那么大的数据内存肯定不行 所以就文件流开着 每次读一段QQ号 判断 到最后关闭流
如果是有序的,那么拆办查找就相当有效了,如果是无序的,那只能通过提取长度和排列的数字进行筛选了,想不出其他办法了。
先把这1亿个QQ排序下,再用2分法查找
先考虑内存,先将文件分成若干等份,分别用模糊查询匹配。
如果要经常查询,可以考虑把数据保存到数据库中,或者只是查询一次,并且QQ号是无序的话,只能顺序查找
这个我没有编程过。但是我用过这样的软件做过这样的事。本地版的txt文件,大约几个G,里面每行一串QQ数据,然后查找QQ号。用过两个软件,其中一种还会建立索引,从小到大排序。速度的话,不快,要几分钟才能查到。
如果你仅仅是追求查找速度的话,可以先排序,排好序的数据查找起来就快了,查找方法也多了。
至于1亿个qq号这样的大批量数据,可以分割到多个小文件。
如果只是追求查找速度的话,可以先排序。
至于你说的1亿个qq号这么大的数据量。咱可以先把它分割成100个(或者说1000个)小文件里头去,都按顺序排好。查找的时候先锁定是去哪个小文件里头去找。
上面大侠说的要多好的硬件配置都瞎扯。算法的问题在一定范围内都是可以空间与时间对换的。
假设1个QQ号8个字节,1亿个QQ号将占用800MB,普通PC的内存都有2GB,不用服务器群、分布式。我认为QQ号全部读到内存中扫描是最快的。
大概两G的文件,内存里面放着就行,最快的方法莫过于借助数据库,当然应该建立索引
http://bbs.csdn.net/topics/391080906
直接导入Hadoop集群,用Mapreduce查一下,应该挺快的,楼上的算法对于大数据来说,都是有极限的,1亿条,读到内存里,电脑直接给你干死机
看看这里介绍的海量数据处理 http://blog.csdn.net/v_july_v/article/details/6279498
可以试试用字典树啊字典树……
建字典库,索引库,索引文件可排序后按照一定的规则存储于不同的磁盘目录中,然后查询是按照规则去不同的索引库所在的目录中查找,速度应该
是你想要的
为什么你们想得这么复杂?
我定义一个数组,char qq[100000000],下标就是QQ号,如果是0代表没有这个QQ号,否则。。
这个数组占内存也就800M
我觉得大家都忽视了一个基本问题,是直接在这文件上查找
还是重新建立查询算法和存储结构的基础上去找,
两种明显会导致不同结果
如果可以重建新的存储方式
方法那就多了去了
建立数据结构也是蛮叼的 机器的配置要很吊 一亿个结构体实例也是
在考虑纯程序算法情况下,如果你读过 编程珠玑 ,你就可以在第一章找到答案,关于小内存大数据快速查找的处理方式。 时间长了不常用淡忘了。 大概你可用的方式包括使用
折半查找算法,分组读取匹配,使用bit位做标记进行运算等等。
非常简单,首先,把字符串转为数字。
然后,hash。
才1亿而已,qq号码最多10位,都是一个四字节整型可以表示的范围内。
看到上面有人扯什么windows,linux,还扯什么超级计算机。。
负责任的告诉你,随便什么计算机,随便什么语言随便写写就好。
数据很典型,全为整数,这是个很有利的条件,
可以先排序,然后采用十分法查找(从首数字依次往后找),应该是最快的了
说点题外话:为了避免这种大数量存储单一的问题,可以考虑按号段存放不同文件。例如,按qq号后四位,分文件存放。
当然,如果既成事实,一定要一个文件里查,很显然,分页都不想帮你分,这些数据肯定也不会帮你排好序。我的看法还是一个个遍历,先比较号码的hash值,相同的再进一步比较数字串是否匹配。考虑到数据量很大,一次读入的行数也要做好限制。
保证内存足够的前提下,可以考虑多线程并发读文件不同行区间,以提高效率。
使用分布式文件存储,可以按照号码的前缀放到不同的文件中,查找时仅需找对应的文件即可
这个问题不在于算法,主要是数据的存储方式,你一个文件存放1亿个QQ号码,这个文件就得超过几G大小,如果你内存够大,全读到内存中虽然也可以,但一般来说不能这样,因为你读文件的复杂度已经是O(n)的量级了。
因为你为了查找一个qq号,就得读取几个G数据到内存,这个开销就太大了,所以这个问题不是算法问题,是数据在磁盘中的结构应如何存储。
一般来说,像数据库这种有自建索引的,比较好弄,但如果你想自建维护磁盘存储结构,就很复杂了,这里说一种简单易懂的。
直接利用磁盘目录做简易索引,由于磁盘本身是有B树索引的,所以管理效率也不低。例如,将QQ号码的前六位作为索引,所有前六位相同的QQ号,都处理存放到一个文件中。然后文件名就以该六位qq号命名。所有文件全放到一个文件夹下可能较难管理,那么可以利用这种思路,上一级目录就用前5位QQ做索引,依次管理,最后整个目录就是一个10叉树。
以前效率不高的原因就是因为读取全部文件太费时间,你将文件打散后存放,读取文件时就很快了,查找的范围也很小了。
整体复杂度 = 几次文件寻找时的随机磁盘寻址+1M左右磁盘读取,接下来直接线性查找都很快。
其实我们发现,这个数量级的查找,复杂度已经不是在内存上了,而是要避免大量从磁盘上的数据读取。数据库做这个事情一般比用文件快,原因是,第一数据库有缓存,之前查过的集合会缓存一段时间,其次,磁盘上有原生的索引结构,比咱们自己用文件树模拟来的高效。
难道不是在数据库里一直点Next Next 吗?
数据仅仅存在一个文件中,一条记录longlong表示64bit,1亿条记录大约600M。
如果仅仅是想最快查找到想要的qq号,都读到内存里遍历一遍就是了。什么建树建hash的都是多此一举,反而会消耗更多的时间。
如果文件很大,达到G或者P级别,建议将数据导入hadoop或者MPP数据库中,
以hadoop环境为例,先将文件上传到hdfs中,hdfs默认64M为一个文件块,这样文件会被分割成若干的小块,然后写mapreduce程序查询,mapreduce仅仅写map阶段就可以,每个map默认会输入一个64M的小文件块进行遍历。
如果想多次查询,新建hive表,表只有一个字段,设置为string类型即可,将文件load到hive表中,然后执行”select <字段名> from where <字段名>= qq号“进行查询,hive会将sql解析成map reduce任务进行分布式执行;
如果想多次查询,并且要求反应速度在毫米级,可以用hive建hbase的外表,用hive将数据加载到hbase中,然后用hbase的get命令查找。
如果是我,首先做一个遍历的程序,先让程序跑起来
程序的短板很可能是读取速度,而不是cpu处理速度
1亿个QQ号码的文件里如果只存了QQ号和密码的话,不用太复杂的算法,用哈希表最简单、最快了,普通机器,2G以内的内存消耗,查找几乎没有时间消耗
一个含有1亿个QQ号码的文件,如何快速的查找某个QQ号码?
限定条件太少了吧!
一个文件含有1亿个QQ号码,文本文件?图片文件?文件中有分隔符吗?是否夹杂其它内容?
只查找一次还是?
是否允许做预处理?
可不可以用天河二号?
out of memory
直接存文件即可,比如qq号为12345678,那么就直接找home/qq/1/2/3/4/5/6/7/8/qq.dat
1.是否允许修改文件或生成新的文件,若不允许,则分两种情况,QQ号在文件中是否有序存储,若有序,则二分查找即可;若无序,则逐一遍历,没有其它办法;
2.若允许修改文件,则可以重新生成或修改文件为QQ有序的文件,然后采用二分查找;
3.若对新文件数目不限定,构建一个目录树,QQ号的第一位数字为第一级目录,第二级目录为第二位数字,......,目录树的最内层是一个空文件a.txt,若有路径指定的qq号,则存在该文件,若没有就不存在a.txt文件,最后所谓的查询,先依据qq号生成一个全路径,然后执行一个文件是否存在的函数调用,依据返回结果即可判定,时间复杂度降到常数,最低时间复杂度,但是空间需求达到最大。
其实,这个问题还是数据储存的问题,要查找的东西太大了。
这种问题很好处理的。我觉得大家都回答不到点子上 。什么树查找呀之类的。都 太高大上。
其实qq号有一个很好的特性 是 数值 。所以假设qq号最长为13位 。这个值 好像是万亿吧。
这个时候你只要建一个万亿的bit数组。把qq号出现代表的数值在 这个bit数组当中置1
一个万亿的bit好像也就几百兆吧。这个的速度 是最快 最省内存的
申请一个足够大的内存 bit[max],多数据进行预处理,比如说QQ号为100,就把bit[100]设置为1 ,默认为0;
处理完,当判断一个QQ号是否存在时,只需判断bit[100]是否为1;
时间复杂度O(1),空间复杂度O(n)
从算法层面:建议楼主看下KMP算法和BMH算法,都是挺常用的
采用分布式处理。按照号码,将数据按照号码大小分文件,再去指定的文件下查找。
如果排序,可以使用二分查找法
或者思考一下hash方式
位数排除法
,最多走11遍就可找到
可以适应拆分查找,应该可以
检索,输入你要查找的QQ号。然后就很快出来。
话说excel、word,甚至txt文件都有查找功能吧,直接输入QQ号,回车就行了啊。
真要算法的话,折半或者10叉树最好吧,学识有限。。
word直接搜索不就好了吗
不同的存储结构查找方式应该也是不一样的
用二叉树或者是有序无序算法来算,。
把文件分割成10000个文件,每个文件10000行,然后在LINUX里写个SHELL,多进程并发寻找
用正则表达式, grep 'qq号码’ 文件名
如果是有序的,那么拆办查找就相当有效了,多线程 算法,优化
有条件的话分布式计算
一位一位的对应比较,应该是最基础的方法了吧,可以使用数据库的概念
选个好点的查找算法,然后利用多线程加速处理
如果是顺序排列的使用折半法找是最简单的
个人觉得分组查询吧,分组然后同时进行
你可以把这些数据保存到SQL SERVER数据库中,再根据sql语句进行查找
有序的话,可以使用跳表,它是在链表的基础上发展而来,在每个结点上另设若干指针,指向它直接后继之后的元素,有序查找时可以逐渐缩小范围,效率还是不错的,就是空间有点大
按首位数字,第二位数字划分
如果数据是可变动的,那么先将QQ号转置为int型,用.sort()方法排序,然后使用二分法或者贪心算法进行匹配,能够在最快的速度下查找到该qq的相应位置,若不能改变数据结构,那么建议使用.copy()方法复制一份临时数据再进行上述操作。【注:以上操作基于python实现最为简单,java等其他语言也可用这种思路实现】
可以尝试着用一个类似冒泡发的组合循环做
打开qq的主文件就能找到,也可以在文件夹上面搜索某个qq号
我觉得可以把这些数据全部放到企业级的缓存中比如solr 这样搜索速度会很快
QQ号每个都不一样吗,如果你愿意,可以到内存里查找
1亿个QQ号要几G吧
谁给你一亿个啊
什么样的文件,表格还是word
使用位图排序的方法
位图排序时,我们需要考虑:给出一个数,如何找到其对应位图的位置,方法就是首先找到该数对应的字节,然后在找到该数对应的位。例如一个QQ号是:983262245,则将bit的98326625位进行标记。bitset是C++提供的一种位集合的数据结构,它让我们可以像使用数组一样使用位,可以访问指定下标的bit位。因此将通过bitset容器进行存储42个qq号码。由于一个字节可以存放8个QQ号码,则4200000000/8/1014/1024 = 500.679Mb,内存合适,通过bit位下表来判断QQ号码是否存在。
#include
#include
#include
#include
#include
using namespace std;
const unsigned int MAX = 4200000010;
typedef unsigned int UT;
bitset bit;
int main(){
//开始存储QQ
for(UT i=1;i<10;i++){
UT qq;
printf("请输入第%d个QQ号:",i);
scanf("%d",&qq);
bit.set(qq);
}
UT qq;
printf("请输入:");
while(scanf("%d",&qq)!=0){
if(bit.test(qq)){
printf("Yes\n");
}
printf("请输入:");
}
return 0;
}
存储:空间占用大约500Mb
查找:时间复杂度为O(1)
作者:hpugym
来源:CSDN
原文:https://blog.csdn.net/hpugym/article/details/80008946
版权声明:本文为博主原创文章,转载请附上博文链接!
数据储存的问题,要查找的东西太大了
两点:
1. 将QQ号按照位数分成若干区域;
2. 按照序号将指定区域划分成若干块,启动多个线程在各自块同时搜索,谁先搜到就结束;
qq是唯一的,先排序下,再用2分法找
你这什么文件啊,word也是文件直接Ctrl+F就好。
你要是数据库文件,直接导入数据库里然后用数据库语句找
其他文件我也不知道咋弄,反正我想不出来你为啥会有那么对QQ号
delete all
remove -f
while(true)
基于布隆过滤器查找,把一个元素加入集合是,k个散列函数把该元素映射为数组中的k个点,把他们置为1,查询时,只要看这些点是不是都是1,就知道集合中有没有它了,这个QQ号的查找应该也可以运用这点
最简单的办法就是字典树。查找效率为Log(N),暴力一点的话就是二分法啦
如果从工程的角度来解决,我会把qq号码按照规则分段存储,然后在基于查找条件,匹配分段,匹配号码。
所以,排序,再分段查找应该实现效率较高的方法吧。毕竟qq号都是数字。
QQ号是唯一的,数据读到内存,以hash方式存储