冒泡法
- 冒泡法
- 冒泡法属于交换排序
- 两两比较大小,交换位置
- 结果分为升序和降序排列
示例:
# num_list = [1, 9, 2, 5, 7, 2, 8, 5, 4, 3]num_list = [1, 2, 3, 4, 5, 6, 7, 8, 9]count = 0 # 统计循环的次数count_swap = 0 # 统计交换的次数length = len(num_list)for i in range(length):flag = False # 设置标志位for j in range(length - i - 1): # 边界考虑,每轮比较后最大的数字排在最右边,因此下次就就无需再次比较,故可使用length-i来排除,后面比较时已经是比较当前索引和后一个索引的大小,因此-1是为了防止越界count += 1if num_list[j] > num_list[j + 1]:flag = True # 如果此判断进不来,说明最近的两个值的顺序就是我们需要的,因此修改标志位num_list[j], num_list[j + 1] = num_list[j + 1], num_list[j] # 封装解构count_swap += 1if not flag: # 当一轮循环结束,标志位没有被修改,说明当前顺序就是我们需要的,可终止循环breakprint(num_list, count, count_swap)
- 总结
- 冒泡法数据需要一轮轮比较
- 可以设定一个标记判断此轮数据是否发生交换,如果没有可结束此轮排序
- 时间复杂度为O(n2)
选择排序
- 选择排序
- 两两比较大小,找出极值(最大值最小值)放在固定位置索引上
- 结果分为生序或者降序
# 算法一m_list = [1, 9, 5, 4, 2, 7, 3, 8, 6]length = len(m_list)for i in range(length):maxindex = ifor j in range(i + 1, length):if m_list[maxindex] < m_list[j]:maxindex = jif i != maxindex:m_list[i], m_list[maxindex] = m_list[maxindex], m_list[i]print(m_list)
算法二:折半计算,优化效率m_list = [1, 9, 3, 2, 7, 5, 8, 4, 6]length = len(m_list)# 每次计算出最大值和最小值,折半计算for i in range(length // 2):maxindex = iminindex = -i - 1minorigin = minindexfor j in range(i + 1, length - i): # 每次循环左右各少比较一个if m_list[maxindex] < m_list[j]:maxindex = jif m_list[minindex] > m_list[-j - 1]:minindex = -j - 1print(maxindex, minindex)if m_list[maxindex] == m_list[minindex]: # 如果最大值和最小值相同,则跳出breakif i != maxindex:m_list[i], m_list[maxindex], = m_list[maxindex], m_list[i]# 如果最小值被交换过,则更新索引if i == minindex or i == length + minindex:minindex = maxindexif minorigin != minindex:m_list[minindex], m_list[minorigin] = m_list[minorigin], m_list[minindex]print(m_list)
插入排序
直接插入排序
- 原理
- 在未排序序列中,构建一个子排序序列,直至所有数据排序完成
- 将待排序的数据,插入到已排序的序列中合适的位置
- 增加一个哨兵,放入待比较值,让它和后面已经排好序的序列比较,找到合适的插入点
- 图示

- 上图中分为三个区域
- 红色字体代表哨兵,即待插入值
- 初始状态的1为假定的有序序列区
- 剩余的无序区
nums = [1, 9, 3, 2, 7, 5, 8, 4, 6]nums = [0] + nums # 增加初始哨兵位,每轮将待比较的数据放入哨兵位length = len(nums)for i in range(2, length):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] # 将哨兵插入,因判断有序序列时减1,因此此时需要在右侧加1print(nums[1:])
