插入排序
插入排序的基本思想是将待排序列表中的每个元素依次插入到已排序好的列表的合适的位置。
def insertion_sort(s):
n = len(s)
for i in range(1, n):
value = s[i]
pos = i
while pos > 0 and value < s[pos - 1] :
s[pos] = s[pos - 1]
pos -= 1
s[pos] = value
第 3 行的外循环的循环变量 i 是列表中待插入元素的索引值。
第 6 - 8 行的内循环将待插入元素 value 依次与索引值为 i-1,i-2,…,0 的元素进行比较,将 比 value 大的元素向后移动,直至找到比 value 小的元素或者 pos=0 为止。
第 9 行将 value 写 入索引值为 pos 的位置,完成插入。
对于长度为 n 的列表 s,内层循环在最坏情况下 (待排序 列表是从大到小的顺序) 的运行次数为 ∑ 1 n − 1 = n ( n − 1 ) / 2 \sum\limits_1^{n-1} = n(n − 1)/2 1∑n−1=n(n−1)/2。因此插入排序算法 的时间复杂度是 O ( n 2 ) O(n^2 ) O(n2)。
归并排序
归并排序的主要思想是将待排序序列分为若干个子序列,每个子序列都是有序的。然后再把有序子序列合并为整体有序序列。
具体来说,它先把数据分成为两半,对每部分分别进行排序,最后将排好序的数据合并成一个有序序列。归并排序算法是采用分治法(Divide and Conquer)的一个非常典型的应用。
def merge_ordered_lists(s1, s2):
t = []
i = j = 0
while i < len(s1) and j < len(s2):
if s1[i] < s2[j]:
t.append(s1[i]); i += 1
else:
t.append(s2[j]); j += 1
t += s1[i:]
t += s2[j:]
return t
def merge_sort(s):
if len(s) <= 1:
return s
mid = len(s) // 2
left = merge_sort(s[:mid])
right = merge_sort(s[mid:])
return merge_ordered_lists(left , right)
快速排序
快速排序是一种著名的排序算法(从这个霸气的名字可以看出)。
以下代码实现了一个易于理解的快速排序算法(并非这个算法的高效实现)。
def qsort(s):
if len(s) <= 1: return s
s_less = []; s_greater = []; s_equal = []
for k in s:
if k < s[0]:
s_less.append(k)
elif k > s[0]:
s_greater.append(k)
else:
s_equal.append(k)
return qsort(s_less) + s_equal + qsort(s_greater)
三者的运行时间
import matplotlib.pyplot as plt
import numpy as np
x = range(100,1001,100)
plt.plot(x, T[0], 'b*--', alpha=0.5, linewidth=1, label='insertion sort')
plt.plot(x, T[1], 'rs--', alpha=0.5, linewidth=1, label='merge sort')
plt.plot(x, T[2], 'go--', alpha=0.5, linewidth=1, label='quick sort')
plt.legend()
plt.xlabel('the length of set')
plt.ylabel('time of sort')
plt.show()
可以看出,在速度上 快速排序>归并排序>插入排序 ,且快速排序的增长速度较快(
O
(
n
2
)
O(n^2)
O(n2)),归并排序和插入排序增长较慢(
O
(
n
log
n
)
O(n\log n)
O(nlogn)).