我写了以下插入排序算法
def insertionSort(L, reverse=False):
for j in xrange(1,len(L)):
valToInsert = L[j]
i=j-1
while i>=0 and L[i] > valToInsert:
L[i+1] = L[i]
i-=1
L[i+1] = valToInsert
return L
编辑:您需要做的就是更改最终的>到<让它反过来工作。
然而,大多数人在这些情况下做了什么?在两个if语句中写入算法两次,其中一个语句是&#和另一个<< s<代替?什么是"正确"通常处理这些变化较小的场景的方法,但它只是完全改变了循环/代码的性质?
我知道这个问题有点主观。
答案 0 :(得分:9)
您可以为less-than运算符使用变量:
import operator
def insertionSort(L, reverse=False):
lt = operator.gt if reverse else operator.lt
for j in xrange(1,len(L)):
valToInsert = L[j]
i = j-1
while 0 <= i and lt(valToInsert, L[i]):
L[i+1] = L[i]
i -= 1
L[i+1] = valToInsert
return L
答案 1 :(得分:1)
选项1:
def insertionSort(L, reverse=False):
# loop is the same...
if reverse:
L.reverse()
return L
选项2:
def insertionSort(L, reverse=False):
if reverse:
cmpfunc = lambda a, b: cmp(b, a)
else:
cmpfunc = cmp
for j in xrange(1,len(L)):
valToInsert = L[j]
i=j-1
while i>=0 and cmpfunc(L[i], valToInsert) > 0:
L[i+1] = L[i]
i-=1
L[i+1] = valToInsert
return L
答案 2 :(得分:0)
您可能会注意到sorted
和list.sort
以及执行任何潜在修饰处理的所有其他函数都有key
参数,而那些专门执行排序的函数也有一个reverse
参数。 (Sorting Mini-HOWTO涵盖了此内容。)
所以,你可以看看它们是如何实现的。不幸的是,在CPython中,所有这些东西都是用C语言实现的。它使用了一个名为“timsort”的自定义算法(在listsort.txt
中描述)。但我认为可以解释这里的关键部分,因为它非常简单。 list.sort
代码与sorted
代码分开,并且它们都分布在一系列函数中。但是如果你只看一下顶级函数listsort
,就可以看到它如何处理reverse
标志:
1982 /* Reverse sort stability achieved by initially reversing the list,
1983 applying a stable forward sort, then reversing the final result. */
1984 if (reverse) {
1985 if (keys != NULL)
1986 reverse_slice(&keys[0], &keys[saved_ob_size]);
1987 reverse_slice(&saved_ob_item[0], &saved_ob_item[saved_ob_size]);
1988 }
为什么在开始和结束时反转列表?好吧,在列表几乎排序的情况下,许多排序算法 - 包括timsort和插入排序 - 将以正确的顺序开始比向后顺序更好。是的,它浪费了一个O(N)reverse
调用,但你已经在做其中一个了 - 并且,因为任何排序算法至少是O(N log N),你的特别是O(N ^ N ^ 2),这不会使它在算法上更糟糕。当然对于小N,更好的排序,以及随机顺序的列表,这浪费的2N非常接近N log N,所以它可以在实践中有所作为。当N变大时,它会消失,但是如果你要分类数以百万计的小list
,而不是几个大的,可能值得担心。
其次,请注意它通过创建反向切片进行反转。至少可能,这可以通过以相反的顺序引用具有list
的原始__getitem__
对象来优化,这意味着两个反转实际上是O(1)。最简单的方法是从字面上创建一个反向切片:lst[::-1]
。不幸的是,这实际上创建了一个新的反转list
,因此timsort包含自己的自定义反向切片对象。但是你可以通过创建ReversedList
类来在Python中做同样的事情。
这在CPython中实际上可能不会更快,因为额外函数调用的成本可能高到足以淹没差异。但是你抱怨两个reverse
调用的算法成本,这解决了问题,实际上与内置排序函数的方式相同。
你也可以看看PyPy是如何做到的。其list
已在listobject.py
中实施。它根据列表包含的内容委托给几个不同的策略类中的一个,但如果你查看所有策略(除了那些无关的策略),它们基本上都做同样的事情:sort
列表,然后是reverse
它。
所以,它对于CPython和PyPy来说已经足够了......对你来说这可能已经足够了。