几种重要排序算法的 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]))
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值