算法
冒泡排序
nums = [5, 9, 1, 6, 11, 15, 99, 7]
swap = 0
times = 0
for i in range(len(nums)-1): #趟数控制,比较趟数为总数减一
times += 1
swap_flag = True #是否产生交换的状态
for j in range(len(nums)-1-i): #内层两两比较
if nums[j] > nums[j+1]:
nums[j], nums[j+1] = nums[j+1],nums[j]
swap += 1
swap_flag = False
if swap_flag: #一趟下来没有交换则判定顺序已经排好,提前退出循环
break
print(nums, times, swap)
核心原则:
- 每一趟进行两两比较都将一个元素放入有序区。
时间复杂度:O(n2)
当一趟比较下来没有进行交换则可以提前结束排序过程。
简单选择排序
nums = [1, 9, 5, 6, 11, 15, 99, 7]
for i in range(len(nums)-1):#控制循环趟数
min_index = i #先假定无序区最左元素为本趟的极值
for j in range(i+1,len(nums)):#内层循环控制被比较元素下标
if nums[min_index] > nums[j]: #满足极值比较条件则保留新下标j
min_index = j
if min_index != i: #如果极值下标没有改变才进行交换
nums[min_index], nums[i] = nums[i], nums[min_index]
print(nums)
核心原则:
- 每趟从无序区选取最大值然后交换到当前无序区最左端。
时间复杂度:O(n2)
原则上比冒泡排序交换次数少所以性能略高于冒泡排序。
双向选择交换
nums = [1, 9, 5, 6]
for i in range(len(nums)//2):#双向选择趟数为元素数整除2
min_index = i
max_index = -i-1 #负索引
for j in range(i+1,len(nums)-i): #循环记住极值索引
if nums[min_index] > nums[j]:
min_index = j
if nums[max_index] < nums[-j-1]:#-2 -3 -4
max_index = -j-1
if min_index == max_index: #两极值下标相等则提前结束
break
if min_index != i:
nums[min_index], nums[i] = nums[i], nums[min_index]
if i == len(nums) + max_index: #如果原最小值索引等于即将交换的最大值索引,则调整最大值索引为交换后的负索引
max_index = min_index - len(nums)
if max_index != -i-1:
nums[max_index], nums[-i-1] = nums[-i-1], nums[max_index]
print(nums)
同时选出最大值和最小值放在两端,可以减少趟数。
插入排序
mynums = [1, 6, 5, 3]
nums = [0] + mynums #添加哨兵位
for i in range(2,len(nums)):
nums[0] = nums[i]
j = i - 1
if nums[j] > nums[0]:#有序区最后一位大于哨兵位才进行挪动
while nums[j] > nums[0]:#选择插入位置,大数依次挪动
nums[j+1] = nums[j]
j -= 1
nums[j+1] = nums[0] #上面循环多减了一次要加回来
print(nums[1:])
核心原则:
- 将待排数插入到有序区合适的位置
时间复杂度:O(n2)
在待排序列前加入一位哨兵位,从索引2开始排序,先将元素放入哨兵位,再插入到有序区合适位置,如果该元素为极值则不变动位置只增大有序区。

浙公网安备 33010602011771号