[英]Finding the index of an element in a list. Binary search or use the index function?
我是python的新手,并且一直在编写一个练习程序,以针对400万个单词的列表检查密码。 我原来的解决方案是这样的(如果列表中包含密码,则将显示true):
import sys
from bisect import bisect_left
script, password, pwlist = sys.argv
password = password+"\r\n"
l=[line for line in open(pwlist)]
l.sort() #Must be sorted for bisect_left to work
print (password <= l[-1]) and (l[bisect_left(l, password)] == password)
然后我意识到我可以改用index方法,如下所示:
import sys
script, password, pwlist = sys.argv
password = password+"\r\n"
l=[line for line in open(pwlist)] #Note we don't need to sort this time
#Catch the "not in list" exception
try:
print (password <= l[-1]) and (l[l.index(password)] == password)
except ValueError:
print "False"
我的第二个版本大大减少了执行时间,因为列表不需要排序。 我是否采用了正确的方法? index()方法如何工作? 如果它适用于未排序的列表,那么肯定不会执行二进制搜索。 任何对此的建议将不胜感激。
是的,在第一个示例中,您首先通过自己的算法(即二进制搜索)设计算法。
在第二个示例中,您仅使用python内置的list.index()
函数。
第二种方法更快,因为对列表进行排序的成本O(N*log(N))
大于对数组进行线性搜索的成本O(N)
。
考虑一下:如果您必须检查多个密码,最好对排序列表进行一次排序和存储 ,然后在排序列表上使用二进制搜索。
当数据结构已经排序时,使用二进制搜索会更好,因为可以在O(log N)中获得它。 对列表进行排序时,以O(N * log N)进行,比线性搜索O(N)慢
在最坏的情况下, list.index
方法的复杂度为O(N),基于其Cpython函数,这是一个优化函数,该函数返回列表中第一个匹配项的索引。 因此,这将是首选的方法,并请注意,在处理排序列表时,二进制搜索非常好。
listindex(PyListObject *self, PyObject *args)
{
Py_ssize_t i, start=0, stop=Py_SIZE(self);
PyObject *v;
if (!PyArg_ParseTuple(args, "O|O&O&:index", &v,
_PyEval_SliceIndex, &start,
_PyEval_SliceIndex, &stop))
return NULL;
if (start < 0) {
start += Py_SIZE(self);
if (start < 0)
start = 0;
}
if (stop < 0) {
stop += Py_SIZE(self);
if (stop < 0)
stop = 0;
}
for (i = start; i < stop && i < Py_SIZE(self); i++) {
int cmp = PyObject_RichCompareBool(self->ob_item[i], v, Py_EQ);
if (cmp > 0)
return PyLong_FromSsize_t(i);
else if (cmp < 0)
return NULL;
}
PyErr_Format(PyExc_ValueError, "%R is not in list", v);
return NULL;
}
但是在您的第一个代码中,您做了很多额外的工作。
首先,您无需使用列表file.readlines()
即可获取文件的所有行,而只需使用file.readlines()
方法即可,而且您还有一个sort方法,这使您的fir方法比第二个方法慢得多。
PS如果你只是要检查的成员,你可以使用一个更Python的方式set
对象保存您的项目,只是使用in
操作数的顺序是O(1)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.