以下的排序算法都是基于关键码排序的,所以在比较关键码大小的时候,代码中都使用了.key。item.key表示item的关键码。在实际应用的时候需要对代码进行适当的修改。直接对数组进行排序的时候,只需要将.key去掉,直接比较元素的大小即可。
"""
coding: utf-8
@author: zhangxiang
"""
# 插入排序 O(n2) (稳定,适应)
def insert_sort(lst):
for i in range(1,len(lst)):
x = lst[i]
j = i
while j>0 and lst[j-1].key > x.key:
lst[j] = lst[j-1]
j = j - 1
lst[j] = x
# 直接选择排序 (非稳定, 非适应)
def select_sort(lst):
for i in range(len(lst)-1):
k = i
for j in range(i, len(lst)):
if lst[j].key < lst[k].key:
k = j
if k != i:
lst[k], lst[i] = lst[i], lst[k]
# 冒泡排序, key() 表示数据的关键码 (稳定, 适应)
def bubble_sort(lst):
for i in range(len(lst)):
for j in range(1, len(lst) - i):
if lst[j-1].key() > lst[j].key():
lst[j - 1], lst[j] = lst[j], lst[j-1]
# 改进的冒泡排序,当一遍搜索的时候没有发现交换操作,证明此时已经排好序 (稳定, 适应)
def bubble_sort2(lst):
for i in range(len(lst)):
found = False
for j in range(1, len(lst) - i):
if lst[j-1].key > lst[j].key:
lst[j-1], lst[j] = lst[j], lst[j-1]
found = True
if not found:
break
# 继续改进的冒泡排序,防止不满足顺序的距离较远的点对排序的影响 (稳定, 适应)
def bubble_sort3(lst):
for i in range(len(lst)):
found = False
for j in range(1, len(lst)-i):
if lst[j-1].key > lst[j].key:
lst[j-1], lst[j] = lst[j], lst[j-1]
found = True
if not found:
break
for k in range(len(lst)-i-2, 0, -1):
if lst[k].key < lst[k-1].key:
lst[k], lst[k-1] = lst[k-1], lst[k]
# 堆排序 O(NlogN) (非稳定, 非适应)
def heap_sort(elems):
def siftdown(elems, e, begin, end):
i, j = begin, begin*2 + 1
while j < end:
if j+1 < end and elems[j+1] < elems[j]:
j += 1
if e < elems[j]:
break
elems[i] = elems[j]
i, j = j, 2*j+1
elems[i] = e
end = len(elems)
for i in range(end//2, -1, -1):
siftdown(elems, elems[i], i, end)
for i in range((end - 1), 0, -1):
e = elems[i]
elems[i] = elems[0]
siftdown(elems, e, 0, i)
# 快速排序 (非稳定,非适应)
def quick_sort(lst):
def quick_rec(lst, l, r):
if l >= r:
return
i, j = l, r
pivot = lst[i]
while(i<j): # while内部存在两个循环模式为了处理的方向一致
while (i<j) and (lst[j].key() >= pivot.key()):
j -= 1
if (i<j):
lst[i] = lst[j]
i += 1
while (i<j) and (lst[i].key() <= pivot.key()):
i += 1
if (i<j):
lst[j] = lst[i]
j -= 1
lst[i] = pivot
quick_rec(lst, l, i-1)
quick_rec(lst, i+1, r)
quick_rec(lst, 0, len(lst)-1)
# 快速排序的另一种实现 (非稳定, 非适应)
def quick_sort2(lst):
def qsort(lst, begin, end):
if begin >= end:
return
pvoit = lst[begin].key
i = begin
for j in range(begin+1, end+1):
if lst[j].key < pvoit:
i = i+1
lst[j], lst[i] = lst[i], lst[j]
lst[i], lst[begin] =lst[begin], lst[i]
qsort(lst, begin, i-1)
qsort(lst, i+1, end)
qsort(lst, 0, len(lst)-1)
# 归并排序 (稳定, 非适应)
def merge_sort(lst):
def merge_pass(lfrom, lto, llen, slen):
i = 0
while i + 2*slen < llen:
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: # 剩下一段,直接对其进行复制
for j in range(i, llen):
lto[j] = lfrom[j]
def merge(lfrom, lto, low, mid, high):
i, j, k = low, mid, low
while (i<mid) and (j<high):
if lfrom[i].key() <= lfrom[j].key():
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
slen, llen = 1, len(lst)
templst = [None]*llen
while slen < llen:
merge_pass(lst, templst, slen, llen)
slen *= 2
merge_pass(templst, lst, slen, llen)
slen *= 2