繁体   English   中英

在列表中查找元素的索引。 二进制搜索还是使用索引功能?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM