一.冒泡排序(原地排序)
①.列表两个相邻的数,如果前面的比后面的大,则交换这两个数
②.一趟排序完成后,则无序区减少了一个数,有序区增加一个数
代码关键:趟无序区范围。
时间复杂度O(n^2)
话不多说上代码
def mao_sort(n, li):
"""
:param n: 需要排序的数据的长度
:param li: 需要排序的列表
:return: 返回排序后的列表
"""
# 外层循环表示循环的躺数n - 1
for i in range(n - 1):
# 内层循环表示在无序区寻找最大(最小)值放到最后
for j in range(n - i - 1):
# 如果后面的小于前面的则前后互换
if li[j + 1] < li[j]:
li[j], li[j + 1] = li[j + 1], li[j]
return li
li = list(map(int, input().split()))
n = len(li)
l_sort = mao_sort(n, li)
print(' '.join(map(str, l_sort)))
冒泡代码的改进
如果在某一趟中并没有交换数据表示排序完成,因此在某一趟没有交换,则表示排序完成,加标志位。
def mao_sort(n, li):
"""
:param n: 需要排序的数据的长度
:param li: 需要排序的列表
:return: 返回排序后的列表
"""
# 外层循环表示循环的躺数n - 1
for i in range(n - 1):
exchange = False # 标志位
# 内层循环表示在无序区寻找最大(最小)值放到最后
for j in range(n - i - 1):
# 如果后面的小于前面的则前后互换
if li[j + 1] < li[j]:
li[j], li[j + 1] = li[j + 1], li[j]
exchange = True # 交换后置为True
# 如果本轮循环没有进行交换,说明已经排序完成,可以提前结束
if not exchange:
break
# print(li)
return li
li = list(map(int, input().split()))
n = len(li)
l_sort = mao_sort(n, li)
print(' '.join(map(str, l_sort)))
二.选择排序(原地排序)
选择排序,在待定排序的数据中选择最小(或者最大)的元素,放到已经排序部分的开头,(或末尾)直到选择所以元素都被排序完成。
时间复杂度O(n^2)
def select_sort(n,li):
"""
:param n: 需要排序的数据长度
:param li: 列表
:return: 返回排序好的数据
"""
# 外层循环表示躺数n - 1趟,
# 由于每一趟选择最小(最大)值,所以最后一趟最后的一个数据绝对为最大值
for i in range(n - 1):
# ans假设的无序区的第一个数据为无序区最小值的下标
ans = i
# 找到无需去的最小值,
for j in range(i + 1, n):
if li[j] < li[ans]:
# 更新最小值下标
ans = j
# 等到内层循环结束找到最小值的下标后
# 使无序区的第一个元素与最小值进行交换
li[i], li[ans] = li[ans], li[i]
return li
li = list(map(int, input().split()))
n = len(li)
s_sort = select_sort(n, li)
print(' '.join(map(str,s_sort)))
三.插入排序(原地排序)
①.初始时手里(有序区)只有一张牌
②.每次(从无序区)摸一张牌,插入到手里已排序的牌的正确位置
时间复杂度O(n^2)
def insert_sort(n, li):
"""
:param n: 排序列表的长度
:param li: 列表
:return: 返回排序好的列表
"""
# 外层循环,遍历无序区
for i in range(1, n):
# j表示有序区的最后一个元素下标
j = i - 1
# val表示无序区的最后一个元素
# (把无序区的第一个元素拿出来)用val存储无序区最后一个元素,后面会被覆盖因此要提前赋值给val
val = li[i]
while j >= 0 and val < li[j]:
# 如果无序区的第一个元素小于有序区的第一个元素则前面的元素后移
li[j + 1] = li[j]
j -= 1
# 把拿出的元素放在合适的位置
val, li[j + 1] = li[j + 1], val
return li
li = list(map(int, input().split()))
n = len(li)
i_sort = insert_sort(n, li)
print(' '.join(map(str, i_sort)))
四.快速排序
快速排序的步骤:
①.找一个基准值x。
②.把列表分成三部分:下于等于x的数字,x,和大于x的数字。
③.左半部分和右半部分递归使用该策略。
时间复杂度:O(nlogn)
def partiton(li, left, right):
"""
:param li: 需要排序的列表数据
:param left: 最左侧
:param right:最右侧
:return:返回基值下标
"""
# 把left作为基值
ind = left + 1
# left = 0
# right = n - 1
for i in range(left + 1, right + 1):
# 遍历需要排序的数据,与基值作比较
if li[i] <= li[left]:
li[i], li[ind] = li[ind], li[i]
ind += 1
# 把基值放到中间
li[left], li[ind - 1] = li[ind - 1], li[left]
# 返回基值的下标
# print(ind - 1)
# print(li)
return ind - 1
# li = list(map(int, input().split()))
# n = len(li)
# a = partiton(li, 0, n - 1)
# print(a)
def quick_sort(li, left, right):
# 必须先判断left < right才能得到基值下标
if left < right:
# mid基值的下标
mid = partiton(li, left, right)
quick_sort(li, left, mid - 1)
quick_sort(li, mid + 1, right)
return li
li = list(map(int, input().split()))
n = len(li)
k_sort = quick_sort(li, 0, n - 1)
print(' '.join(map(str, li)))
五.归并排序
归并排序算法步骤:
①.先把数组分成两部分
②.每部分递归处理变成有序
③.将两个有序列表合并起来
时间复杂度:O(nlogn)
# 合并两个list
def merge(left_li, right_li):
"""
:param slet_li: 列表1
:param right_li: 列表2
:return: 返回合并的列表
"""
# li用来存储合并后的数据
li = []
while len(left_li) != 0 and len(right_li) != 0:
if left_li[0] <= right_li[0]:
li.append(left_li.pop(0))
else:
li.append(right_li.pop(0))
li.extend(left_li)
li.extend(right_li)
return li
# li1 = list(map(int, input().split()))
# li2 = list(map(int, input().split()))
# print(merge(li1,li2))
def merge_sort(li):
"""
:param li: 列表
:return: 返回归并函数merge()
"""
# 如果列表长度为1就不需要排序
if len(li) < 2:
return li
mid = len(li) // 2
left = merge_sort(li[:mid])
right = merge_sort(li[mid:])
return merge(left, right)
li = list(map(int, input().split()))
a = merge_sort(li)
print(' '.join(map(str, a)))