吃透排序算法之遍历排序
排序算法不仅仅是无序到有序, 其中涉及了数组的遍历处理, 划分的模板运用, 甚至其中还设计到了数组到树的堆化处理. 可以说吃透了排序算法, 可以成为一个合格的算法初学者了.
本系列文章带领读者吃透排序算法, 掌握数组的处理方式, partition
模板, 数组的二叉树形式并进行堆化处理.
吃透排序算法之遍历排序为本系列的遍历排序介绍, 主要介绍几种入门的排序, 本文主要涉及:
- 冒泡排序
- 选择排序
- 插入排序
- 希尔排序
冒泡排序
冒泡排序是第一个要学习的排序算法, 过程像冒泡一样. 假设数组长度为n
, 冒泡排序将进行n
趟, 每一趟元素交换过程如同气泡从小到大, 最终得到一个排序好的数组.
冒泡排序交换相邻元素, 内层数组每次会后移一位, 直到排序好的位置, 外层数组控制n
趟.
nums = [1, 3, 2, 5, 4, 6]
i = 0
while i < len(nums):
j = 0
while j < (len(nums)-1)-i:
if not (nums[j] <= nums[j+1]):
nums[j], nums[j+1] = nums[j+1], nums[j]
j += 1
i += 1
print(nums) # [1, 2, 3, 4, 5, 6]
进一步的过程中冒泡排序可能就排序完成, 可以通过flag
优化算法.
nums = [1, 3, 2, 5, 4, 6]
i = 0
while i < len(nums):
j, swap = 0, False # 定义flag
while j < (len(nums)-1)-i:
if not (nums[j] <= nums[j+1]):
swap = True # 赋值flag
nums[j], nums[j+1] = nums[j+1], nums[j]
j += 1
if not swap: # 通过flag提前结束
break
i += 1
print(nums) # [1, 2, 3, 4, 5, 6]
选择排序
选择排序的处理方式和冒泡排序有很大不同, 顾名思义选择一个最值来放到有序区. 每轮只进行一次交换, 比冒泡少多了. 数组被划分有有序区和无序区, 每次选择最小元素和下一个无序位置交换. 最小值可以选择索引, 索引可以初始化成和当前无序位置相同的数值, 并不需要设置一个最小的值-inf
.
nums = [1, 3, 2, 5, 4, 6]
i = 0
while i < len(nums):
j, minidx = i, i
while j < len(nums):
if nums[j] < nums[minidx]:
minidx = j
j += 1
nums[i], nums[minidx] = nums[minidx], nums[i]
i += 1
print(nums) # [1, 2, 3, 4, 5, 6]
插入排序
插入排序类似于冒泡排序, 主要是因为相邻元素, 不同点就是冒泡是向数值尾部冒泡, 插入则是想数组头部冒泡. 这个说法可能不准确, 因为冒泡过程可能随时停止, 更像是插入, 所以名为插入排序.
nums = [1, 3, 2, 5, 4, 6]
# 插入排序相临
i = 0
while i < len(nums):
j = i
while j > 0:
if not (nums[j-1] <= nums[j]):
nums[j], nums[j-1] = nums[j-1], nums[j]
j -= 1
i += 1
print(nums) # [1, 2, 3, 4, 5, 6]
希尔排序
试想一种情况, [2,3,4,5,6,1]
如果使用插入排序, 1
要跨过整个数组, 显然有点拖累. 是否可以加速这一过程呢? 考虑是否可以去掉相邻的考虑, 改成跨gap
的相隔呢? 这样就可以避免这种情况出现. 数组将在gap
缩小的过程趋近整体有序, 最终gap
为1时退化成插入排序.
nums = [2, 3, 4, 5, 6, 1]
def insert(gap): # 插入排序相隔gap
i = 0
while i < len(nums):
j = i
while j > 0:
if not (nums[j-gap] <= nums[j]):
nums[j], nums[j-gap] = nums[j-gap], nums[j]
j -= gap
i += gap
gap = int(len(nums)/2) # 通常gap选取N/2
while gap > 0:
insert(gap)
gap -= 1
print(nums) # [1, 2, 3, 4, 5, 6]
小结
本文主要对遍历排序做介绍和使用python
实现了基本过程. 学习了冒泡排序的实现和优化, 了解了选择排序的交换原理和实现, 学习了插入排序的实现和其极端情况的优化希尔排序.