Python基础排序算法

Python基础排序算法

排序算法的稳定性

假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,则称这种排序算法是稳定的;否则称为不稳定的。

我们举一个例子就好理解了:

假设有如下的元组:(4, 1) (3, 1) (3, 7) (5, 6)
按照每个元组的第一个位置的元素进行排序
排法1:(3, 1) (3, 7) (4, 1) (5, 6) 稳定,维持次序(3, 1)和(3, 7)的次序
排法2:(3, 7) (3, 1) (4, 1) (5, 6) 不稳定,次序被改变

冒泡排序

较为简单的排序算法之一,它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果顺序(如从大到小、首字母从Z到A)错误就把他们交换过来。走访元素的工作是重复地进行,直到没有相邻元素需要交换,也就是说该元素列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端(升序或降序排列),就如同碳酸饮料中二氧化碳的气泡最终会上浮到顶端一样,故名“冒泡排序”。

冒泡排序是稳定的排序算法。

冒泡排序

def bubble_sort(alist):
	"""
	冒泡排序
	稳定的
	最优时间复杂度:O(n^2)
	最坏时间复杂度:O(n^2)
	"""
	n = len(alist)
	for j in range(n-1):
		for i in range(n-1-j):
			if alist[i] > alist[i+1]:
				alist[i], alist[i+1] = alist[i+1], alist[i]

if __name__ == '__main__':
	alist=[1,23,5,1,2,3,45]
	bubble_sort(alist)
	print(alist)

选择排序

一种简单直观的排序算法。它的工作原理是:第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。以此类推,直到全部待排序的数据元素的个数为零。

选择排序是不稳定的排序算法。

选择排序

def selection_sort(alist):
	"""
	选择排序
	不稳定
	最优时间复杂度:O(n^2)
	最坏时间复杂度:O(n^2)
	"""
	n = len(alist)
	for i in range(n):
		index = 0 
		for j in range(1, n-i):
			if alist[j] > alist[index]:
				index = j
		alist[index], alist[n-1-i] = alist[n-1-i], alist[index]

if __name__ == '__main__':
	ls=[]
	selection_sort(ls)
	print(ls)

插入排序

插入排序,一般也被称为直接插入排序。对于少量元素的排序,它是一个有效的算法。插入排序是一种最简单的排序方法,它的基本思想是将一个记录插入到已经排好序的有序表中,从而一个新的、记录数增1的有序表。在其实现过程使用双层循环,外层循环对除了第一个元素之外的所有元素,内层循环对当前元素前面有序表进行待插入位置查找,并进行移动。

插入排序是稳定的排序算法。

插入排序

第一种实现想法:

def insert_sort(alist):
	"""
	插入排序
	稳定的
	最优时间复杂度:O(n)
	最坏时间复杂度:O(n^2)
	平均情况:O(n^2)

	插入排序:首先把数列第一个位置的的元素看成一个已排好序的数列,
	然后分别遍历后面的元素,依次插入前面抽象出来的已排好序的数列即可。
	"""
	n = len(alist)
	for i in range(1, n):
		index = i
		for j in range(i-1,-1,-1):
			if alist[j] > alist[index]:
				alist[index], alist[j] = alist[j], alist[index]
				index = j

if __name__ == '__main__':
	ls = [23,45,213,4,1,2,4]
	insert_sort(ls)
	print(ls)

另一种实现想法:

def insert_sort_2(alist):
	"""
	插入排序2
	"""
	n = len(alist)
	for i in range(1,n):
		 while i-1 >= 0:
		 	if alist[i-1] > alist[i]:
		 		alist[i-1], alist[i] = alist[i], alist[i-1]
		 		i -= 1
		 	else:
		 		break


if __name__ == '__main__':
	ls = [2,3,4,345,35,1,32]
	insert_sort_2(ls)
	print(ls)

希尔排序

希尔排序(Shell’s Sort)是插入排序的一种又称“缩小增量排序”(Diminishing Increment Sort),是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。该方法因 D.L.Shell 于 1959 年提出而得名。
希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至 1 时,整个文件恰被分成一组,算法便终止。

希尔排序是不稳定的排序算法。

希尔排序

def shell_sort(alist):
	"""
	希尔排序
	最优时间复杂度:根据步长序列(gap)的不同而不同 (O(n^1.3) 根据数学计算得来)
	最坏时间复杂度:O(n^2)
	不稳定
	平均情况:O(nlogn)~O(n^2)
	"""
	n = len(alist)
	gap = n // 2
	while gap:
		for j in range(gap, n):
			i = j
			while i - gap >= 0:
				if alist[i] < alist[i - gap]:
					alist[i], alist[i - gap] = alist[i - gap], alist[i]
					i -= gap
				else:
					break
		gap //= 2


if __name__ == "__main__":
	ls=[3,3,5,23,5,45,6,10]
	shell_sort(ls)
	print(ls)

快速排序

快速排序,计算机科学词汇,适用领域Python,c++等语言,是对冒泡排序算法的一种改进。

快速排序算法通过多次比较和交换来实现排序,其排序流程如下:
(1)首先设定一个分界值,通过该分界值将数组分成左右两部分。
(2)将大于或等于分界值的数据集中到数组右边,小于分界值的数据集中到数组的左边。此时,左边部分中各元素都小于分界值,而右边部分中各元素都大于或等于分界值。
(3)然后,左边和右边的数据可以独立排序。对于左侧的数组数据,又可以取一个分界值,将该部分数据分成左右两部分,同样在左边放置较小值,右边放置较大值。右侧的数组数据也可以做类似处理。
(4)重复上述过程,可以看出,这是一个递归定义。通过递归将左侧部分排好序后,再递归排好右侧部分的顺序。当左、右两个部分各数据排序完成后,整个数组的排序也就完成了。

快速排序是不稳定的排序算法。

快速排序

def quick_sort(alist, first = 0, last = None):
	"""
	快速排序
	最优时间复杂度:O(nlogn)
	最坏时间复杂度:O(n^2)
	不稳定
	"""
	if last == None:
		last = len(ls) - 1 
	if first >= last:
		return
	mid_value = alist[first]
	low = first
	high = last
	while high > low:
		while high > low and alist[high] >= mid_value:
			high -= 1
		alist[low] = alist[high]

		while high > low and alist[low] < mid_value:
			low += 1
		alist[high] = alist[low]
	#当循环退出时,low = high

	alist[high] = mid_value
	quick_sort(alist, first, low - 1)
	quick_sort(alist, low + 1, last)


if __name__ == '__main__':
	ls = [23,4,1,2,2,34,53,65]
	quick_sort(ls)
	print(ls)

归并排序

归并排序是建立在归并操作上的一种有效,稳定的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。

归并操作的工作原理如下:
第一步:申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
第二步:设定两个指针,最初位置分别为两个已经排序序列的起始位置
第三步:比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
重复步骤3直到某一指针超出序列尾
将另一序列剩下的所有元素直接复制到合并序列尾

归并排序是稳定的排序算法。

归并排序

def merge_sort(alist):
	"""
	归并排序
	最优时间复杂度:O(nlogn)
	最坏时间复杂度:O(nlogn)
	稳定的
	"""
	n = len(alist)
	if n <= 1:
		return alist
	mid = n // 2
	left = merge_sort(alist[:mid])
	right = merge_sort(alist[mid:])
	return merge(left, right)

def merge(llist, rlist):
	"""
	合并
	"""
	ls = []
	left = 0
	right = 0
	while left < len(llist) and right < len(rlist):
		if llist[left] <= rlist[right]:
			ls.append(llist[left])
			left += 1
		else:
			ls.append(rlist[right])
			right += 1
	ls.extend(llist[left:])
	ls.extend(rlist[right:])
	return ls

if __name__ == '__main__':
	ls = [2,4,5,6,23,3,5,7,7,2,1]
	sorted_ls = merge_sort(ls)
	print(sorted_ls)
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值