我刚刚编写了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
事实证明这是无限循环,这对我来说是完全可以理解的。有人能指出我出了什么问题吗?
答案 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]