快排基本思想:
按照某种标准将序列划分为“小记录”和“大记录”,并通过递归不断划分。
思想如图所示:
其中,R为枢轴元素
代码实现如下:
def quick_sort(lst):
qsort_rec(lst, 0, len(lst)-1)
def qsort_rec(lst, l, r):
if l > r:
return #分段无记录或只有一个记录
i = l
j = r
pivot = lst[i] #lst[i]是初始空位
while i < j:
while i < j and lst[j] >= pivot: #大记录,寻找比pivot大的元素
j -= 1 #向左扫描比pivot大的元素
if i < j: #lst[j] < pivot
lst[i] = lst[j]
i += 1 #小于pivot的元素移到左边
while i < j and lst[i] <= pivot:
i += 1
if i < j: #lst[i] > pivot
lst[j] = lst[i]
j -= 1 #大记录移到右边
lst[i] = pivot #将pivot存入其最终位置
qsort_rec(lst, l, i-1) #递归处理左半区间
qsort_rec(lst, i+1, r) #递归处理右半区间
归并排序
基本思想:
将两个或更多有序序列合并为一个有序序列。
代码如下:
def merge(lfrom, lto, low, mid, high):
i, j, k = low, mid, low
while i < mid and j < high: #记录两段段首记录中较小的
if lfrom[i] <= lfrom[j]:
lto[k] = lfrom[i]
i += 1
else:
lto[k] = lfrom[j]
j += 1
k += 1
while i < mid: #复制第一段记录
lto[k] = lfrom[i]
i += 1
k += 1
while j < high: #复制第二段记录
lto[k] = lfrom[j]
j += 1
k += 1
def merge_pass(lfrom, lto, llen, slen):
i = 0
while i + 2*slen < llen: #归并长slen的两段
merge(lfrom, lto, i, i + slen, i + 2 * slen)
i += 2 * slen
if i + slen < llen: #剩下两段,后段长度小于slen
merge(lfrom, lto, i, i + slen, llen)
else: #只剩下一段,复制到表lto
for j in range(i,llen):
lto[j] = lfrom[j]
def merge_sort(lst):
slen, llen = 1, len(lst)
templst = [None] * llen
while slen < llen:
merge_pass(lst, templst, llen, slen)
slen *= 2
merge_pass(templst, lst, llen, slen) #结果存回原位
slen *= 2
print lst, templst
需要注意的是,此算法实现归并另外开辟了一片同样大小的存储区,也就是建立了另一个同样大小的表,把一遍归并的结果放在那里,在一遍归并做完后,在保存归并结果的新表里存储加倍长度的有序序列,而且原来的表已经闲置了。在这种情况下,可以考虑调换两个表的角色,在原表张积累下一遍归并的结果。