一:冒泡排序
原理:
(1)列表每两个相邻的数,如果前面比后面大,则交换这两个数。
(2)一趟排序完成后,则无序区减少一个数,有序区增加一个数。
(3)代码关键点:趟、无序区范围
如上图所示,这是一个未排序的列表,冒泡排序的做法是从第0位开始,与它下一个数进行比较,如果前面比后面大,则交换这两个数,每次比较后再与下一个数比较,直到指针指到第7位时,与第8位进行比较之后,能成功得将最大的数排到了第8位也就是最后一位,此时将该列表分为有序区与无序区,如下图所示,有序区中的数为9,无序区的数为剩下的数。这样一个趟就可以使有序区的数增加一个。举下图为例,设 i 为第几趟,只需进行列表的长度减一(len(list)-1)趟就能成功排序,因为此时无序区只剩下一个数,而这个数是经过比较后剩下来最小的一个数,不需要再进行比较。
j 指的是指针的位置,第i趟时,无序区有n - 1个数,
第0趟时指针最后指到的是第7位,第1趟时指针最后指到的是第6位,列表长度是9,所以指针指在n - i - 1处。(range顾头不顾尾)
def bubble_sort(list):
for i in range(len(list) - 1): ##总共排n-1趟
exchange = False #如果某一趟完成了不必继续进行排序
for j in range(len(list)-i-1): #第i趟时,无序区有n-i个数,指针指在n-i-1处
if list[j] > list[j+1]:
list[j],list[j+1] = list[j+1], list[j]
exchange = True
if not exchange:
return
exchange开关是可以减少不必要的操作,如果某一趟完成了,没有再进行交换不必继续进行排序。
时间复杂度O(n2)
二:选择排序
原理:
(1)一趟排序记录最小的数,放到第一个位置
(2)再一趟排序记录无序区最小的数,放到第二个位置,以此类推
(3)算法关键点:有序区和无序区、无序区最小数的位置。
def select_sort(list):
for i in range(len(list)-1): ##i时第几趟
min_value = i ##无序区第一个数
for j in range(i+1,len(list)): ##第i趟无序区的第一个数为list【i】,从无序区第一个数开始和后面的数进行比较
if list[j] < list[min_value]:
min_value = j
list[i],list[min_value] = list[min_value],list[i]
同理,只需进行n-1趟就能成功排序,先设无序区第一个数为最小值,再与后面的数进行比较,如果后面的数比它小则交换,i表示的是第几趟,第i趟无序区的第一个数为list【i】,从无序区第一个数开始和后面的数(list【i+1】)进行比较。
时间复杂度O(n2)
三:插入排序
原理:
(1)初始时手里(有序区)只有一张牌
(2)每次(从无序区)抽一张牌,根据比较插入到手里已有牌(有序区)的正确位置
def insert_sort(list):
for i in range(1,len(list)): #i指的是抽到的牌的下标
temp = list[i]
j = i-1 #j指的是手里的牌
while j >= 0 and list[j] > temp:
list[j+1] = list[j]
j -= 1
list[j+1] = temp
print(list)
li = [6,5,9,3,4,8,2,7,1]
insert_sort(li)
假设列表首个元素是初始时手里有一张牌,这一张牌是有序区,每次抽一张牌,抽到最后一张牌,从list(1)抽到最后,所以一共抽了n-1次,且是从第二个元素开始,所以是for i in range(1,len(list)-1)。每次抽到的牌的下标为i,手里的牌是i的前一张牌也就是j=i-1。当抽到的牌比手里的牌小的时候,就将手里的牌往右移动一位,当抽到的牌大于手里的牌或者抽到的牌已经到最左边了,停止while循环,将抽到的牌放到手里的牌右边,以此类推
时间复杂度O(n2)