原地快排:使用额外O(1)的空间复杂度实现快速排序。
思路:
考虑快排的其中一步,我们从无序列表中取出头部元素,执行若干步交换操作后,该元素左侧的元素均小于该元素,右侧的元素均不小于该元素。返回该元素的最终位置,并对该元素左右两侧的子列表进行快排。
我们可以将该元素反复与其后的元素比较。在代码中用l
表示该元素当前的索引,用r
表示列表中最右侧的未与该元素比较的元素的索引。如果其后的元素小于该元素,则将两个元素的位置交换,并修改该元素的索引(l+=1
)。如果其后的元素大于等于该元素,则将后方元素和数组最右未比较元素交换,并修改数组最右未比较元素的索引(r-=1
)。
class QuickSort:
def __init__(self, a):
self.a = a
def sort(self, l_, r_):
l, r = l_, r_-1
if l >= r: return
while l < r:
if self.a[l] > self.a[l+1]:
self.a[l], self.a[l+1] = self.a[l+1], self.a[l]
l += 1
else:
self.a[l+1], self.a[r] = self.a[r], self.a[l+1]
r -= 1
self.sort(l_, l)
self.sort(l+1, r_)
def quick_sort(self):
self.sort(0, len(self.a))
if __name__ == '__main__':
c = QuickSort(a=[9, 0, 3, 5, 8, 4, 7, 1, 6, 2])
c.quick_sort()
print(c.a)
每一步排序中,该元素和数组中的每个元素进行一次比较,即r_ - l_
次比较。每次比较伴随一次交换,即r_ - l_
次交换。
感觉这个问题在C++单向链表上比较有意义,因为在此场景下可以实现稳定的排序。有空再写一篇吧。