幾種重要排序算法的 Python 實現

冒泡排序

最基本的排序,使用交換相鄰項的操作每次搜索剩餘列表中的最大值,並將其“冒”出。

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]))
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章