冒泡排序&&选择排序&&插入排序&&希尔排序

排序算法

 

排序算法的稳定性

 
  排序算法(Sorting algorithm)是一种能将一串数据依照特定顺序进行排列的一种算法。

  稳定性:稳定排序算法会让原本有相等键值的纪录维持相对次序。也就是如果一个排序算法是稳定的,当有两个相等键值的纪录R和S,且在原本的列表中R出现在S之前,在排序过的列表中R也将会是在S之前。

  当相等的元素是无法分辨的,比如像是整数,稳定性并不是一个问题。然而,假设以下的数对将要以他们的第一个数字来排序。
 

(4, 1)  (3, 1)  (3, 7)5, 6

  在这个状况下,有可能产生两种不同的结果,一个是让相等键值的纪录维持相对的次序,而另外一个则没有:

(3, 1)  (3, 7)  (4, 1)  (5, 6)  #(维持次序)
(3, 7)  (3, 1)  (4, 1)  (5, 6)  #(次序被改变)

 
  不稳定排序算法可能会在相等的键值中改变纪录的相对次序,但是稳定排序算法从来不会如此。不稳定排序算法可以被特别地实现为稳定。作这件事情的一个方式是人工扩充键值的比较,如此在其他方面相同键值的两个对象间之比较,(比如上面的比较中加入第二个标准:第二个键值的大小)就会被决定使用在原先数据次序中的条目,当作一个同分决赛。然而,要记住这种次序通常牵涉到额外的空间负担。
 

一、冒泡排序

在这里插入图片描述
  游标从头走到尾,走一次,选出最大值93,第二次走,走到n-1,选出最大值77,以此类推
 

1.1 代码实现:

def bubble_sort(alist):
"""冒泡排序"""
	n = len(alist)
	for j in range(n-1):
		for i in range(0,n-1-j):
			if alist[i] > alist[i+1]:
				alist[i],alist[i+1] = alist[i+1],alist[i]
# 我写的过程:先写内层循环(从头走到尾),再写外层循环(内层循环经历多少遍)
# i和j关系的确定:
# 第一次:i 0~n-2 (从第一个走到倒数第二个) range(0,n-1) j=0
# 第二次:i 0~n-3  (从第一个走到倒数第三个)  range(0,n-1-1) j=1
# 第三次:i 0~n-4  (从第一个走到倒数第四个)  range(0,n-1-2) j=2
#  j=n i range(0,n-1-j)
if __name__ == "__main__":
	li = [54,26,93,17,77,31,44,55,20]
	print(li)
	bubble_sort(li)
	print(li)

 

1.2 时间复杂度

  最优时间复杂度:O(n) (表示遍历一次发现没有任何可以交换的元素,排序结束。)
  最坏时间复杂度:O(n^2)
  稳定性:稳定
 

二、选择排序

在这里插入图片描述
  选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理如下。首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。

  选择排序的主要优点与数据移动有关。如果某个元素位于正确的最终位置上,则它不会被移动。选择排序每次交换一对元素,它们当中至少有一个将被移到其最终位置上,因此对n个元素的表进行排序总共进行至多n-1次交换。在所有的完全依靠交换去移动元素的排序方法中,选择排序属于非常好的一种。
 

2.1 代码实现

# 举个例子,然后再写
# alist = [54,226,93,17,77,31,44,55,20]
#           0  1  2  3  4  5  6  7  8
# 54后面的所有数里挑一个最小的和54比,min = alist[3]; alist[0],alist[3] = alist[3],alist[0]
# alist = [17,226,93,54,77,31,44,55,20]
# 17后面的所有数里挑一个最小的和17比,min = alist[8],alist[1],alist[8] = alist[8],alist[1]
# alist = [17,20,93,54,77,31,44,55,226]
# …………
def select_sort(alist):
"""选择排序"""
#详细手把手写一下:
#第一步,写一次的代码
	n = len(alist)
	min_index = 0
	for i in range(1,n):
		if alist[min_index] > alist[i]:
			min_index = i
	alist[0],alist[min_index] = alist[min_index],alist[0]

#第二步,加上外置循环
	n = len(alist)
	for j in range(0,n-1)
		min_index = j
		for i in range(j+1,n):
			if alist[min_index] > alist[i]:
				min_index = i
		alist[0],alist[min_index] = alist[min_index],alist[0]
	

 

2.2 时间复杂度

  最优时间复杂度:O(n^2)
  最坏时间复杂度:O(n^2)
  稳定性:不稳定(考虑升序每次选择最大的情况)
 

三、插入排序

在这里插入图片描述
  插入排序(Insertion Sort)是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上,在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。
 

3.1 和选择排序的异同

  同:都是假设左边是排序的,右边是无序的
  异:选择排序是第一次在所有里挑一个最小的,放最左边;第二次在除了刚才挑的,其他的数里再挑一个最小的,放第二个,以此类推(操作无序这边)
     插入排序是取出第一个数,构成有序序列,然后再看第二个数,按大小插入到有序序列中,再看第三个数,按大小插入到有序序列中,以此类推(操作有序这边)
 

3.2 代码实现

def insert_sort(alist)
	i = 1
	while i > 0:#元素到头时停止
		if alist[i] < alist[i-1]:
			alist[i],alist[i-1] = alist[i-1],alist[i]
			i -= 1 #因为往前移了一个位置
		else: #因为如果比前一个元素大,那肯定比前面所有元素都大,就直接跳出循环即可
			break 

#增加外置循环
	for j in range(1,n) #从右边的无序序列中取出多少个元素执行这样的过程
		i = j
		#执行从右边的无序序列中取出第一个元素,即i位置的元素,然后将其插入到前面正确位置
		while i > 0:#元素到头时停止
			if alist[i] < alist[i-1]:
				alist[i],alist[i-1] = alist[i-1],alist[i]
				i -= 1 #因为往前移了一个位置
			else: #因为如果比前一个元素大,那肯定比前面所有元素都大,就直接跳出循环即可
				break 

 

3.3 时间复杂度

  最优时间复杂度:O(n) (升序排列,序列已经处于升序状态)
  最坏时间复杂度:O(n^2)
  稳定性:稳定

 

四、希尔排序

 
  希尔排序(Shell Sort)是插入排序的一种。也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。该方法因DL.Shell于1959年提出而得名。 希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。
 
在这里插入图片描述
 
  上图中,按照gap=4,分成了54,77,20 ; 26,31 ; 93,44 ; 17,55 四个序列,每个序列按照插入排序来操作
 
在这里插入图片描述
  一次操作之后,gap变成2,再来一次;
  gap变成1,再来一次,完成

 

4.1 代码实现

def shell_sort(alist):
    n = len(alist)
    # 初始步长
    gap = n / 2
    while gap > 0:
        # 按步长进行插入排序
        for i in range(gap, n):
            j = i
            # 插入排序
            while j>=gap and alist[j-gap] > alist[j]:
                alist[j-gap], alist[j] = alist[j], alist[j-gap]
                j -= gap
        # 得到新的步长
        gap = gap / 2

alist = [54,26,93,17,77,31,44,55,20]
shell_sort(alist)
print(alist)

 

4.2 时间复杂度

  最优时间复杂度:根据步长序列的不同而不同
  最坏时间复杂度:O(n2)
  稳定性:不稳定

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值