冒泡排序
最基本的排序,使用交換相鄰項的操作每次搜索剩餘列表中的最大值,並將其“冒”出。
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]))