IndexError:pop索引超出范围(python)

时间:2012-10-15 01:02:31

标签: python sorting merge

我编写了以下合并排序代码:

def merge_sort(self,a):

    #console.log(len(a))
    if len(a) <= 1:
        return a
    left = []
    right = []
    result = []
    middle = int(len(a)/2)
    print middle

    left = a[:middle] #set left equal to the first half of a
    right = a[middle:] #set right equal to the second half of a
    print left
    print right

    left = self.merge_sort(left)
    right = self.merge_sort(right)
    result = self.merge(left, right)

    return result

然后合并代码:

def merge(self, left, right):
    result = []
    while len(left) > 0 or len(right) > 0:

        if len(left) > 0 and len(right) > 0:
            if left[0] <= right[0]:
                result.append(left[0])
                left = left.pop(1)    #remove the first element from left

        elif len(left) > 0:
            result.append(left[0])
            left = left.pop(1)    #remove the first element from left

        elif len(right) > 0:
            result.append(right[0])
            right = right.pop(1)  #remove the first element from right

        else:
            result.append(right[0])
            right = right.pop(1)
    return result

我发送数组:     a = [12,0,232]

我得到以下输出(不同的迭代),并在最后一个输出我得到错误,请帮助我不明白为什么错误是有的,谢谢!:

(1 [12] [0,232]) (1 [0] [232])

追踪(最近一次通话): 合并中的...... \ Sort_Class.py“,第116行     left = left.pop(1)#remove第一个元素从左边开始 IndexError:pop index超出范围

2 个答案:

答案 0 :(得分:3)

您的代码存在问题,例如在此选择中它们都存在:

result.append(left[0])
left = left.pop(1)

这应该是:

result.append(left.pop(0))

问题是:

  1. Python列表使用基于0的索引,因此left[0]是列表的第一个元素left[1],因此left.pop(0)弹出第一个元素,而left.pop(1)弹出第二个元素< / LI>
  2. left.pop(1)返回弹出的元素,而不是列表,因为它会改变列表。 left = left.pop(1)在这里没有多大意义。
  3. 不需要同时按left[0]获取第一个元素,然后弹出它left.pop(0)

答案 1 :(得分:0)

我认为.pop()不符合你的想法。例如,这一行:

left = left.pop(1)    #remove the first element from left

不会从left中删除“第一个”(即第零个)元素。 .pop(1)是第二个要素:

>>> a = [10,20,30,40]
>>> a.pop(1)
20
>>> a
[10, 30, 40]

此外,如果您设置a = a.pop(1),则a不再是列表,而是数字:

>>> a = [10,20,30,40]
>>> a = a.pop(1)
>>> a
20

也无效。您可以使用del left[0]left = left[1:]或仅result.append(left.pop(0))替换这些内容,如刚刚发布的答案中所述。 :^)修复显示另一个问题,但是:由于这里的逻辑,你的代码被无限循环捕获:

    if len(left) > 0 and len(right) > 0:
        if left[0] <= right[0]:

如果left[0] > right[0],则没有分支,leftright都没有任何问题,而且您被困。如果你调整这个来为这种情况添加一个右分支行为,你的代码似乎可以工作:

>>> import random
>>> def check():
...     for length in range(1, 10):
...         for trial in range(10000):
...             v = [random.randrange(-10, 10) for i in range(length)]
...             assert merge_sort(v) == sorted(v)
...     return True
... 
>>> check()
True