【问题标题】:My quick sort code gives me wrong result when printed second time第二次打印时,我的快速排序代码给了我错误的结果
【发布时间】:2021-11-09 21:05:45
【问题描述】:

我是 Python 新手,这是我编写的快速排序代码:

def Quick(List):
    if len(List) <= 1:
        return List
    pivot = List[0]
    l_idx = 0
    r_idx = len(List) - 1
    
    while l_idx != r_idx:
        while List[l_idx] < pivot and l_idx < r_idx:
            l_idx += 1
        while List[r_idx] > pivot and l_idx < r_idx:
            r_idx -= 1
        if l_idx < r_idx:
            List[l_idx], List[r_idx] = List[r_idx], List[l_idx]    
    
    List = Quick(List[0: (l_idx)]) + [List[l_idx]] + Quick(List[(l_idx + 1):])
    return List

我要排序的列表是 [598, 862, 950, 953, 373, 981, 201, 258, 427, 669]。

如果我运行以下代码,我会得到

xxx = [598, 862, 950, 953, 373, 981, 201, 258, 427, 669]
print(xxx)
# Gives me: [598, 862, 950, 953, 373, 981, 201, 258, 427, 669]
print(Quick(xxx))
# Gives me:[201, 258, 373, 427, 598, 669, 862, 950, 953, 981], which is the correct result.
print(xxx)
# Gives me: [427, 258, 201, 373, 598, 981, 953, 950, 862, 669], which is not the correct result.

我想知道为什么我得到的结果与我第二次打印列表“xxx”时返回的结果完全不同。谢谢!!

【问题讨论】:

  • 您希望第二个print(xxx) 打印您的排序列表还是原始未排序列表?
  • 我认为它应该给我排序列表。
  • 那么你需要将你的Quick函数的返回结果赋回名称xxx,例如xxx = Quick(xxx)。然后print(xxx) 将打印排序列表。
  • 我试过了,它确实给出了正确的结果,但我想知道我的 Quick(List) 出了什么问题,当我第二次打印它时,它给了我列表的全新顺序.
  • 我认为你的算法返回一个完整的新列表,而不是在原始列表上工作,因此原始列表没有按预期排序(由于第一次调用该方法,即使它的元素也有点乱序,不是递归的)。

标签: python-3.x algorithm sorting recursion


【解决方案1】:

原因是您为函数内的List(输入变量)分配了一个新值。因此,此变量的作用域在函数内部,您无法在函数外部看到对 List 的更改(请参阅 this post 中的更多详细信息)。

但是,正如 cmets 中所提到的,您可以将结果分配给 xxx,当通过 xxx = Quick(xxx) 返回它时。

【讨论】:

    【解决方案2】:

    在转向解决方案之前,让我们先谈谈正在发生的事情。第三个打印输出是算法第一次迭代后的列表,为什么会这样?好吧,当您执行List = something 时,您只会更改变量引用的列表,而不是列表本身。这意味着 List 不再引用作为参数传递的列表。您基本上可以像这样逐个元素地将该语句更改为一个元素:

    for index, elem in enumerate(Quick(List[0: (l_idx)]) + [List[l_idx]] + Quick(List[(l_idx + 1):])):
        List[index] = elem
    

    要记住的另一件事是,当您使用List[:] 语句时,您正在创建一个新列表,并且此切片发生的修改不会影响原始列表。因此,递归调用中发生的任何更改都将被原始列表忽略。

    我已经修改了您的方法,使其在每一步都适用于原始列表,因为我们需要两个附加参数,即当前迭代的开始索引和结束索引,模拟你 List[:]。我们开始吧。

    def BQuick(List, _from, _to):
        if _to - _from <= 0:
            return List
    
        pivot = List[_from]
    
        l_idx = _from
        r_idx = _to
    
        while l_idx != r_idx:
    
            while List[l_idx] < pivot and l_idx < r_idx:
                l_idx += 1
    
            while List[r_idx] > pivot and l_idx < r_idx:
                r_idx -= 1
    
            if l_idx < r_idx:
                List[l_idx], List[r_idx] = List[r_idx], List[l_idx]
    
        BQuick(List, _from, l_idx - 1)
        BQuick(List, l_idx + 1, _to)
    
        return List
    
    
    def Quick(List):
        return BQuick(List, 0, len(List) - 1)
    
    

    由于我们对原始列表进行了所有操作,因此无需在最后指定返回。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-01-07
      • 2018-10-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多