简体   繁体   English

合并排序列表索引超出范围

[英]Merge sort list index out of range

I'm trying to do a basic merge sort in python, but every time I run the code I get the error 我正在尝试在python中进行基本的合并排序,但每次运行代码时我都会收到错误

"... if x[0] < y[0]: IndexError: list index out of range " “...如果x [0] <y [0]:IndexError:列表索引超出范围”

And I'm not sure where I'm going wrong. 而且我不确定我哪里出错了。 Here's the code: 这是代码:

def merge(x,y):
    merged = []
    while len(x) > 0 or len(y) > 0:
        if x[0] < y[0]: #this is where it is telling me the list index is out of range
            merged.append(x[0])
            del x[0] 
        else:
            merged.append(y[0])
            del y[0]
    print merged

s1 = raw_input()
s2 = raw_input()
nums1 = map(int, s1.split())
nums2 = map(int, s2.split())

merge(nums1,nums2)

Thank you in advance! 先感谢您!

Once you've taken all the elements from x , there is no x[0] , but you try to compare it to y[0] anyway. 一旦你从x获取了所有元素,就没有x[0] ,但你还是试着将它与y[0]进行比较。 If you exhaust y first, there is no y[0] , but you still try to compare it to x[0] anyway. 如果先耗尽y ,则没有y[0] ,但仍然会尝试将其与x[0]进行比较。 Once one list is exhausted, you can't keep doing those comparisons. 一旦列表用完,您就无法继续进行这些比较。

Your current while statement will run while either of the two lists are non-empty (because of the or condition) but you're not covering the case where just one is empty. 您当前的while语句将在两个列表中的任何一个非空(因为or条件)时运行,但您不会覆盖只有一个为空的情况。 In the case where one list is empty, and you attempt to compare the first in each list, you'll get the error you're seeing. 如果一个列表为空,并且您尝试比较每个列表中的第一个列表,则会收到您看到的错误。

For example, consider the simple lists {1,2} and {3,4} . 例如,考虑简单列表{1,2}{3,4} You start with: 你从:

list 1 = {1,2}, list 2 = {3,4}, merged = {}

Your first loop iteration will check the first element of both lists and decide it needs to use the first list, leaving you with: 您的第一个循环迭代将检查两个列表的第一个元素,并决定它需要使用第一个列表,让您:

list 1 = {2}, list 2 = {3,4}, merged = {1}

Your second loop iteration will check the first element of both lists and decide it needs to use the first list again, leaving you with: 你的第二个循环迭代将检查两个列表的第一个元素,并决定它需要再次使用第一个列表,让你:

list 1 = {}, list 2 = {3,4}, merged = {1,2}

Your third loop iteration will check the first element of both lists and fall in a heap because there is no first element in the first list. 你的第三个循环迭代将同时检查列表和下降的第一个元素在堆,因为第一个列表中没有第一个元素。

The solution is to simply ensure that, if one list has become empty, just use the other list without checking the contents. 解决方案是简单地确保,如果一个列表变空,只需使用另一个列表而不检查内容。 There are two ways I've done that in the past. 我过去有两种方法可以做到这一点。

First, within the while loop, you can check if each list is empty before comparing. 首先,在while循环中,您可以在比较之前检查每个列表是否为空。 If one is, select from the other list. 如果是,请从其他列表中选择。 In other words, pseudocode like: 换句话说,伪代码如:

while len(list1) > 0  or len(list2) > 0:
    if    len(list1) == 0:       use list2
    elsif len(list2) == 0:       use list1
    elsif list1[0] <= list2[0]:  use list1
    else:                        use list2

Second, and this is the one I tend to prefer since it seems cleaner having the finishing logic outside of the main loop, compare lists until one is empty, then process the rest of the other list: 第二,这是我倾向于选择的那个,因为在主循环之外使用完成逻辑似乎更清晰,比较列表直到一个为空,然后处理其他列表的其余部分:

while len(list1) > 0  and len(list2) > 0:
    if    list1[0] <= list2[0]:  use list1
    else:                        use list2

 while len(list1) > 0:  use list1
 while len(list2) > 0:  use list2

Only one of those final while loops will do anything since you only get to that point if one of the lists is empty. 只有其中一个最终while循环才会执行任何操作,因为如果其中一个列表为空,则只能到达该点。

You can also optimise it in languages that support mass transfer since you know you have to transfer a large block from one array to another (you don't need to do it one element at a time). 您还可以使用支持传质的语言对其进行优化,因为您知道必须将大块从一个阵列传输到另一个阵列(您不需要一次只执行一个元素)。 I'm referring there to something like Python's: 我指的是类似Python的东西:

dst[28:31] = list2[12:15]

or C's memcpy() function. 或C的memcpy()函数。

The last section then becomes something like: 最后一节变成了类似的东西:

 if len(list1) > 0:  use rest of list1
 else:               use rest of list2

It's a simple "either-or" since you know: 这是一个简单的“或者 - 或者”,因为你知道:

  • at least one of the lists is empty, otherwise you'd still be in the main loop; 至少有一个列表是空的,否则你仍然在主循环中; and
  • you know the other list is non-empty since you're only pulling an element from one list each time. 你知道另一个列表是非空的,因为你每次只从一个列表中提取一个元素。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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