以功能方式实现快速排序

时间:2017-04-28 21:43:19

标签: python quicksort

我刚刚编写了Python quicksort - 我希望我有最短的方法来做到这一点(非常像功能方式),所以我写道:

def quicksort(List):
    if len(List)>1:
        Pivot=List[0]            
        return quicksort(lessThan(List,Pivot)) + [Pivot] + quicksort(moreThan(List,Pivot))
    else:
        return List

def lessThan(List, Pivot):
    lessThanList = [x for x in List if x <= Pivot]
    return lessThanList

def moreThan(List, Pivot):
    moreThanList = [x for x in List if x > Pivot]
    return moreThanList

不幸的是,它会跳过所有多重出现的数字。好吧,这似乎是合乎逻辑的,但是当我试图改进这种写作时:

def lessThan(List, Pivot):
    lessThanList = [x for x in List if x <= Pivot]
    return lessThanList

事实证明这是无限循环,这对我来说是完全可以理解的。有人能指出我出了什么问题吗?

3 个答案:

答案 0 :(得分:1)

由于您使用第一个元素作为数据透视表,防止无限递归的最简单方法是避免将第一个元素传递给lessThan。像这样添加两个字符:

return quicksort(lessThan(List[1:],Pivot)) + ...
                               ^^

清除?它为第一个元素(数据透视)传递之外的列表。

但请注意,您仍然可以获得与原始列表长度相等的递归;例如,想象排序[2, 2, 2, 2, 2, 2, 2, 2, 2, 2]

答案 1 :(得分:1)

任何等于pivot的其他项目都会丢失 - 您的lessThan或moreThan列表都不会包含它们,并且您只在两个子列表之间插入[pivot]的一个实例。将lessThan更改为使用<=可以让您进行无限递归;在每个步骤中,子列表必须严格小于原始列表,否则您没有取得任何进展。一种方法是:

return quicksort(lessThan(List,pivot)) + equalTo(List,pivot) + quicksort(moreThan(List,pivot))

其中equalTo()的工作方式与您现有的lessThan()&amp; moreThan()

答案 2 :(得分:1)

正如其他人所指出的那样,您的疏忽是您在分区列表时没有移除枢轴。如果你喜欢用函数式编写,Python提供了富有表现力的语言结构,  像extended iterable unpacking一样,我们可以利用这有助于避免容易犯的错误:

def quicksort(seq):
    if len(seq) <= 1:
        return seq
    pivot, *rest = seq
    smaller = quicksort([x for x in rest if x <= pivot])
    larger = quicksort([x for x in rest if x > pivot])
    return smaller + [pivot] + larger

行动中:

>>> quicksort([10,2,5,3,1,6,7,4,2,3,4,8,9])
[1, 2, 2, 3, 3, 4, 4, 5, 6, 7, 8, 9, 10]