004---普通排序

冒泡排序

原理:
从第一个数开始,与它下一个相邻的数比较大小。比它大就交换位置,比它小不交换,就拿这个相邻数与下一个数比较。重复下去,到最后一个元素时。就得到了一个最大的值。
列表的长度是len(a),但是当只剩下最后一个数需要比较大小时,它已经是最小的了,所以一共要走len(a) - 1次
第一次需要比较的次数是len(a) - 1 得到一个最大值
第二次需要比较的次数是len(a) - 1 - 1
第三次需要比较的次数是len(a) - 1 - 1 - 1
所以每次需要比较的次数是 len(a) -i -1

优化:如果列表本身就是有序的[1,2,3,4,5,6,7,8,9],或者中途排好序了。那么还需要比较大小交换位置吗?

时间复杂度:
最坏:O(n^2)
最好:就是本身就是有序的时候,O(n)

 1 li = [8, 3, 4, 7, 2, 5, 6, 9, 1]
 2 # li = [1,2,3,4,5,6,7,8]
 3 
 4 
 5 def bubble(li):
 6     for i in range(len(li) - 1):                        # 总次数
 7         flag = False                                    # 加标志位
 8         for j in range(len(li) - i - 1):                # 需要比较的次数
 9             if li[j] > li[j + 1]:
10                 li[j], li[j + 1] = li[j + 1], li[j]     # 交换两个数
11                 flag = True
12         print('第%d次排序:'%(i+1), li)
13         if not flag:
14             break                                       # 某一次比较时列表里没有数需要交换。退出外层循环
15 
16 
17 bubble(li)
18 print(li)
选择排序

原理:取一个基准数,暂且定为第一个,拿第一个数和剩下的数中最小的数交换位置,之后再拿第二个数和它剩下的数中最下的数交换位置,依次进行下去
核心:基准数和剩下的数比较大小时,注意记录此时最小数的索引
例如:
# li = [2,4,5,1,6,9,7,3,8]
li = [3,4,5,2,6,9,7,1,8]

li = [1,4,5,2,6,9,7,3,8]
li = [1,2,5,4,6,9,7,3,8]
li = [1,2,3,4,6,9,7,5,8]
li = [1,2,3,4,5,9,7,6,8]
li = [1,2,3,4,5,6,7,9,8]
li = [1,2,3,4,5,6,7,8,9]

优化:当基准数已经是最小数的时候,不需要交换
 1 li = [2, 4, 5, 1, 6, 9, 7, 3, 8]
 2 # li = [1,2,3,4,5,6,7,8,9]
 3 
 4 def select_sort(li):
 5     # 总共需要交换的次数 i代表基准数的索引
 6     for i in range(len(li) - 1):
 7         mid = i
 8         # 剩下的数中比它小就交换位置,并记录那个最小的数的索引
 9         # 优化,如果后面的数都比基准数大,说明他已经是最小的数了。不需要进行交换。
10         for j in range(i + 1, len(li) - 1):
11             if li[j] < li[mid]:
12                 # 此时最小数的索引
13                 mid = j
14         if mid != i:
15             li[mid], li[i] = li[i], li[mid]
16             print('第%d次排序' % (i + 1), li)
17             
18 select_sort(li)
19 print(li)
插入排序

原理:
和我们平时抓牌一样。
假设手里已经有了第一张牌,之后的每一次抓牌与手里的牌的比较大小(从右往左),大就放这张牌的后面。小就把这张牌往后移动,与手里剩下的牌比较。直到大于手里的牌。
重复以上步骤,当我们的牌抓完时,手里的牌也就排好序了,所以一共要抓len(li) - 1 次

注意点:如果抓到的牌,一直比手里的牌小,j就要一直减,但是减到列表的第一个索引的数往右移动一个位置的时候就可以不用减了,直接把抓到的牌放到第一个索引即可。

时间复杂度:
最好:O(n):当抓到的牌一直比手里的大的时候,就不需要移动牌,直接放牌就行了。不走while循环
最坏:O(n^2)
 1 li = [8, 3, 4, 7, 2, 5, 6, 9, 1]
 2 # li = [1, 2, 3, 4, 5, 6, 7, 8, 9]
 3 
 4 
 5 def insert_sort(li):
 6     for i in range(1, len(li)):             # i 抓到的牌的索引。从一开始
 7         tmp = li[i]                         # 临时存放抓到的牌的值
 8         j = i - 1                           # 手里的牌的索引。从右开始
 9 
10         while j >= 0 and li[j] > tmp:       # 手里的牌大于抓的牌  j往右移动一位置 注意点
11             li[j + 1] = li[j]
12             j -= 1
13 
14         li[j + 1] = tmp                      # 放牌
15 
16 
17 insert_sort(li)
18 print('排完序之后:', li)
原文地址:https://www.cnblogs.com/xjmlove/p/10176639.html