冒泡排序
最基本的排序,使用交换相邻项的操作每次搜索剩余列表中的最大值,并将其“冒”出。
def bubble(alist):
first = 0
last = len(alist) - 1
while first < last:
for i in range(first, last):
if alist[i] > alist[i+1]:
alist[i], alist[i+1] = alist[i+1], alist[i]
last -= 1
return alist
if __name__ == '__main__':
print(bubble([7,3,4,5,4,9,6]))
通常冒泡排序非常低效,但是因为它每次遍历整个列表未排序的部分,所以可以 early stop 来改进该算法:
def shortBubble(alist):
already = False
first = 0
last = len(alist) - 1
while first < last and not already:
already = True
for i in range(first, last):
if alist[i] > alist[i+1]:
alist[i], alist[i+1] = alist[i+1], alist[i]
already = False
last -= 1
return alist
if __name__ == '__main__':
print(shortBubble([7,3,4,5,4,9,6]))
选择排序
可以看做是冒泡排序的一种改进,每次遍历列表只做一次交换:
def select(alist):
last = len(alist) - 1
while last > 0:
index = 0
for i in range(last+1):
if alist[i] > alist[index]:
index = i
alist[index], alist[last] = alist[last], alist[index]
last -= 1
return alist
if __name__ == '__main__':
print(select([7,3,4,5,4,9,6]))
插入排序
通过在列表低端维护一个有序子列表的方式实现最终的排序。不同于冒泡排序的交换操作,插入排序使用更有效率的“移位操作”,通过不断移动有序子列表元素的位置,将未排序的目标元素插入的正确位置:
def insert(alist):
if len(alist) == 1:
return alist
else:
for i in range(1, len(alist)):
current = alist[i]
loc = i
while loc > 0 and alist[loc-1] > current:
alist[loc] = alist[loc-1]
loc -= 1
alist[loc] = current
return alist
if __name__ == '__main__':
print(insert([7,3,4,5,4,9,6]))
希尔排序
插入排序的一种改进,将原始列表分解为多个不相邻的小列表,这些小列表由原始列表中相隔为“gap”的元素组成,分别对这些小列表使用插入排序,使原始列表变得更有序。减小gap,重复以上操作,直到gap为1,退化为一般的插入排序:
def shell(alist):
gap = len(alist) // 2
while gap > 0:
for startpoint in range(gap):
alist = gapInsertSort(alist, startpoint, gap)
gap = gap // 2
return alist
def gapInsertSort(alist, startpoint, gap):
for i in range(startpoint, len(alist), gap):
current = alist[i]
loc = i
while loc > 0 and alist[loc-1] > current:
alist[loc] = alist[loc-1]
loc -= 1
alist[loc] = current
return alist
if __name__ == '__main__':
print(shell([7,3,4,5,4,9,6]))
归并排序
归并排序采用分而治之的思想优化排序算法,是一种递归算法,不断将列表二分,在左半部分列表和右半部分列表上调用 mergeSort 函数,则认为这两部分它们已经被排序,那么当前要做的就是把这两部分合并,即按顺序挑选两部分中最小的项赋给结果列表。当列表长度为 0 或 1 时,到达递归出口:
def mergeSort(alist):
if len(alist) <= 1:
return alist
else:
mid = len(alist) // 2
left = alist[:mid]
right = alist[mid:]
mergeSort(left)
mergeSort(right)
i, j, k = 0, 0, 0
while i < len(left) and j < len(right):
if left[i] < right[j]:
alist[k] = left[i]
i += 1
else:
alist[k] = right[j]
j += 1
k += 1
while i < len(left):
alist[k] = left[i]
i += 1
k += 1
while j < len(right):
alist[k] = right[j]
j += 1
k += 1
return alist
if __name__ == '__main__':
print(mergeSort([5,6,4,3,0,9,7]))
快速排序
快速排序与归并排序很类似,但是不需要额外的存储。每次选定一个 pivot value,两个标记位置,不断相向的移动标记,比较标记位置列表元素与 pivot value 的大小关系,如果不符合规定的大小关系,则定位,当两个标记均定位,交换标记处的两个元素,重复操作,直到两个标记 converge,即找到了 split point,将 pivot value 插入到 split point 并以该点为界分裂列表,在子列表重复快速排序:
def quick(alist):
quickSort(alist, 0, len(alist)-1)
return alist
def quickSort(alist, first, last):
if first >= last:
return alist
else:
leftmark = first + 1
rightmark = last
while leftmark <= rightmark:
leftfind = False
rightfind = False
if alist[leftmark] <= alist[first]:
leftmark += 1
else:
leftfind = True
if alist[rightmark] >= alist[first]:
rightmark -= 1
else:
rightfind = True
if leftfind and rightfind:
alist[leftmark], alist[rightmark] = alist[rightmark], alist[leftmark]
alist[first], alist[rightmark] = alist[rightmark], alist[first]
quickSort(alist, first, rightmark-1)
quickSort(alist, rightmark+1, last)
return alist
if __name__ == '__main__':
print(quick([5,6,4,3,0,9,7]))
堆排序
利用最小二叉堆删除堆顶元素操作实现的排序算法,最小二叉堆的实现可以看我的这篇文章:https://blog.csdn.net/Whisper321/article/details/90755329 先将需要排序的列表转化为由列表表示的最小(最大)二叉堆,然后利用堆顶元素必为当前堆中最小(最大)值的性质弹出堆顶元素完成排序:
def heapSort(alist):
heap = buildHeap(alist)
res = []
while len(heap) > 1:
res.append(delMin(heap))
return res
def buildHeap(alist):
size = len(alist)
alist.insert(0, 0)
heap = alist
i = size // 2
while i > 0:
sortDown(heap, i)
i -= 1
return heap
def delMin(heap):
minimum = heap[1]
heap[1] = heap[-1]
heap.pop()
sortDown(heap, 1)
return minimum
def sortDown(heap, i):
while i*2 <= len(heap) - 1:
mc = minChild(heap, i)
if heap[i] > heap[mc]:
heap[i], heap[mc] = heap[mc], heap[i]
i = mc
return heap
def minChild(heap, i):
if i*2 + 1 > len(heap) - 1:
return i*2
else:
if heap[i*2] < heap[i*2 + 1]:
return i*2
else:
return i*2 + 1
if __name__ == '__main__':
print(heapSort([5,6,4,3,0,9,7]))