##文章摘自:https://blog.csdn.net/qq_38165374/article/details/73703943
一 冒泡排序
遍历列表,比较相邻的两个元素的大小,如果第一个数小于第二个数继续移动,否则交换两个元素的位置 。
时间复杂度:平均:O(n²),最好:O(n),最坏:O(n2),稳定性:稳定。
# coding=utf-8
def bubbling(li):
length = len(li)
# 控制循环的总次数
for j in range(0,length-1):
# 控制每次循环时比较位置元素的
for i in range(0,length-j-1):
if li[i] > li[i+1]:
li[i],li[i+1] = li[i+1],li[i]
return li
if __name__ == "__main__":
lists = [54, 26, 93, 77,17, 77, 31, 44, 55, 20]
l = bubbling(lists)
print l
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
效果图
二 插入排序
从无需列表中依次选出与有序列表作比较。
时间复杂度O(n^2),最优时间复杂度O(n),稳定性:稳定。
# coding=utf-8
# 插入排序,假设第一个元素为有序列表,第二个到最后的元素为无需列表
# 从无序列表中依次取出元素和有序列表进行比较,如果小于就交换位置
def insert_sort(li):
# 获取长度
length = len(li)
# 从第二个元素开始遍历控制比较总次数
for j in range(1,length):
# 取出的元素和前面的元素依次比较如果小于就交换位置
for i in range(j,0,-1):
if li[i]<li[i-1]:
li[i],li[i-1] = li[i-1],li[i]
else:
break
return li
if __name__ == "__main__":
lists = [17, 20, 999,31, 44, 54, 55, 77, 93, 226]
L=insert_sort(lists)
print L
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
效果图
三 选择排序
假设一个元素为最小值,用其他的元素依次和它进行比较,如果不是最小就交换位置。
时间复杂度:平均,最好,最坏都为O(n²),稳定性:不稳定
#coding=utf-8
def selection(li):
# 获取长度
length = len(li)
# 控制循环的总次数,假设下角标为j的元素为最小值
for j in range(0,length):
mix_index = j
# 从下一个元素开始遍历,依次和下角标为j的元素比较
# 如果比假设最小值的元素小则记录这个下角标
for i in range(j+1,length):
if li[i]<li[mix_index]:
mix_index = i
# 比较更新之后的下角标是否与假设的下角标一致
# 如果不一致交换这两个元素的位置
if mix_index != j:
li[mix_index],li[j] = li[j],li[mix_index]
return li
if __name__ == '__main__':
lists = [54, 226, 93, 17, 77, 31, 44, 55, 20]
l=selection(lists)
print l
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
效果图
红色表示当前最小值, 黄色表示已排序序列,蓝色表示当前位置
四 快速排序
原理:通过一次排序将数据分割为两部分,其中一部分的所有值都比另一部分小,通过递归的方式将数据变为有序数列
时间复杂度:平均O(n log n) ,最好O(n log n) ,最坏O(n²),稳定性:不稳定。
方法:
1.在数列中挑出一个元素作为中间值,
2.重新排序数列,将比中间值小的放到前面,比中间值大的放到基准后面
3.递归,将两个独立的部分非别排序
#coding=utf-8
# 快速排序选择一个中间值,比中间值小的放到左边,否则放到右边
def quick_sort(li,start,end):
'''
:param li 列表:
:param start 列表的起始位置:
:param end 列表的结束位置:
:return 排序后的列表:
'''
# 递归结束条件
if start>=end:
return li
# 假设中间值为start位置上的值
mid_value = li[start]
# 左侧游标的起始位置和右侧游标的起始位置
left_cur = start
right_cur = end
# 满足左侧游标<右侧游标的位置,就执行循环
while left_cur <right_cur:
# 右侧游标的值大于中间值,并且左右游标没有重合就移动右侧游标
# 否则赋值给左侧游标
while left_cur < right_cur and li[right_cur]>=mid_value:
right_cur-=1
li[left_cur] = li[right_cur]
while left_cur < right_cur and li[left_cur]<mid_value:
left_cur+=1
li[right_cur] = li[left_cur]
# 将假设的中间值放到两个游标指向的位置(中间位置)
li[right_cur] = mid_value
# 递给快速排序中间值左侧的序列
quick_sort(li,0,right_cur-1)
# 递归快速排序中间值右侧的序列
quick_sort(li,right_cur+1,end)
return li
if __name__ == '__main__':
lists = [17, 20, 1,999, 31, 44, 54, 55, 77, 93, 226]
l=quick_sort(lists,0,len(lists)-1)
print l
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
效果图
五 希尔排序
将无需列表按照一定的步长分割为多个子序列,分别对子序列进行插入排序,之后在缩短步长,重复之前的操作,直到最后步长为1。
时间复杂度:平均:O(nlogn)~O(n2),最好:O(n1.3次方),最坏:O(n²),稳定性:不稳定
方法:
1. 指定一个步长,一般是列表长度的一半
2. 按照步长将每一个子序列进行插入排序
3. 再次缩短步长重复操作,直到最后的步长是1,进行最后一次插入排序。
# coding=utf-8
def shell_sort(li):
# 取出列表的长度
length = len(li)
# 设置初始步长
gap = length // 2
# 控制循环次数,步长>=1
while gap >= 1:
# 使用插入排序,比较相邻的两个元素之间相差一个步长
# 判断与前一个元素的大小,如果小于继续移动,否则交换位置
for i in range(gap,length):
for j in range(i,0,-1):
if li[i] < li[i-1]:
li[i],li[i-1] = li[i-1],li[i]
else:
break
gap = gap // 2
return li
if __name__ == '__main__':
lists = [17, 20, 1,999, 31, 44, 54, 55, 77, 93, 226]
l=shell_sort(lists)
print l
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
效果图