递归线性搜索 - 返回列表索引

时间:2010-11-28 05:57:44

标签: python recursion

我有一个搜索列表('l')的函数搜索,如果找到则返回True,否则返回False。我希望它返回密钥的索引如果找到,如果没有找到则返回False,但我对我的返回语句应该是什么感到困惑。这是我的代码:

def search(l,key):
    """
    locates key in list l.  if present, returns location as an index; 
    else returns False.
    PRE: l is a list.
    POST: l is unchanged; returns i such that l[i] == key; False otherwise.
    """

    if l:   # checks if list exists
        if l[0] == key:     # base case - first index is key
            return True

        s = search(l[1:], key)      # recursion
        if s is not False:          
            return s

    return False            # returns false if key not found

非常感谢任何帮助,谢谢。

4 个答案:

答案 0 :(得分:1)

对于你的基本案例,你刚刚在索引0处找到了该项,对吗?返回0。

if l[0] == key:     # base case - first index is key
    return 0

对于你的递归部分,让我们考虑一下返回什么。假设项目在索引5处。因为我们已经通过递归调用传递了一个元素的列表,它将找到它并返回4.(4,不是5.你明白为什么吗?)

在返回索引之前,我们需要添加一个来取消索引。

s = search(l[1:], key)      # recursion
if s is not False:          
    return s + 1

答案 1 :(得分:1)

你需要跟踪索引。因为你的最终返回值[如果真的搜索发生]是布尔值,所以你必须改变它。
我想下面的代码应该对你有所帮助,但是要彻底测试它,因为我只是试图克服意图而没有彻底测试逻辑 -

def search(l,key,idx=0):
"""
locates key in list l.  if present, returns location as an index; 
else returns False.
PRE: l is a list.
POST: l is unchanged; returns i such that l[i] == key; False otherwise.
"""

if l:   # checks if list exists
    if l[0] == key:     # base case - first index is key
    return idx

    s = search(l[1:], key, (idx + 1))      # recursion
    if s is not False:          
        return s

return False            # returns false if key not found

答案 2 :(得分:1)

您的API设计存在严重缺陷。

>>> False == 0
True

您的导师正在为您提供惊喜。例如:

where = search(["non-foo", "not-foo"], "foo") # returns False
if where == 0:
    print "foo is in pole position"
    # but "foo" isn't even a candidate

让它在失败时返回None。试试这个:

>>> def search(alist, key, pos=None):
...     if pos is None: pos = len(alist) - 1
...     if pos < 0: return None
...     if key == alist[pos]: return pos
...     return search(alist, key, pos - 1)
...
>>> search([1,2,3], 4) # -> None
>>> search([1,2,3], 3)
2
>>> search([1,2,3], 2)
1
>>> search([1,2,3], 1)
0
>>> search([], 1) # -> None
>>>

此方法的其他功能:(1)向您介绍“隐藏”args的概念,可以在非递归函数中使用局部变量时使用。 (2)避免所有字符串切片的成本。

=========================================

为了@ inspectorG4dget的好处,这是我对@ anirvan的答案的重构:

def xsearch(l,key,idx=0):
    if l:   # checks if list exists
        if l[0] == key:     # base case - first index is key
            return idx
        s = xsearch(l[1:], key, (idx + 1))      # recursion
        if s is not False:          
            return s
        #### and if s is False, it falls through and returns False ####
        #### so it can return s unconditionally!                   ####
    return False            # returns false if key not found

def ysearch(l,key,idx=0):
    if l:   # checks if list exists
        if l[0] == key:     # base case - first index is key
            return idx
        return ysearch(l[1:], key, (idx + 1))      # recursion
    return False            # returns false if key not found
    #### above statement is better put closer to the `if` ####

def zsearch(l,key,idx=0):
    if not l:   # checks if list exists
        return False
    if l[0] == key:     # base case - first index is key
        return idx
    return zsearch(l[1:], key, (idx + 1))      # recursion

答案 3 :(得分:0)

问题在于您正在切割列表的尾部而不保留有关切片发生位置的任何信息。

实际上,您根本不需要对列表进行切片,因为您可以在列表中进行索引查找。

线性搜索的算法是原始递归的,所以如果你能想出一个迭代的解决方案,那么递归解决方案很容易达到(反之亦然)。

所以迭代解决方案看起来像这样:

for every integer i between zero and length of list
    if the element at position i in the list is equal to the key
        return i
else
   return "I couldn't find it"

我们将迭代解决方案转换为递归解决方案基本上意味着将循环转换为函数调用,其参数是下一循环迭代的值。循环变量是i并且正在搜索列表。为了让你从练习中学习,我会把它留在那里。