1.插入排序
思路:
初始状态,所有元素无序,假设划分为左右两侧,左侧有序,右侧无序
先遍历右侧无序部分,
再遍历左侧有序部分,
找到在有序的数组中,第一个大于无序元素nums[i]的有序元素nums[j],即为插入位置
nums = [5, 3, 6, 4, 1, 2, 8, 7]
for i in range(1, len(nums)): # 遍历无序
for j in range(i): # 遍历有序
if nums[j] > nums[i]: # 找到插入位置
ins = nums[i]
nums.pop(i)
nums.insert(j, ins)
break
print(nums)
2.选择排序
思路:
初始状态,所有元素无序,假设划分为左右两侧,左侧有序,右侧无序
每次从无序中,找到最小的元素,放到有序的末尾,也就是和无序的第一个元素相交换
nums = [5, 3, 6, 4, 1, 2, 8, 7]
for i in range(len(nums) - 1): # 更新无序数组的第一个元素的位置
minInd = i
for j in range(i, len(nums)): # 找出未排序数组中最小值的下标
if nums[j] < nums[minInd]:
minInd = j
nums[i], nums[minInd] = nums[minInd], nums[i] # 把最小值加到有序数组末尾
print(nums)
3.冒泡排序
思路:
重复遍历数组,依次比较相邻的元素,最大数/最小数会慢慢“浮”到数组的末尾。
nums = [5, 3, 6, 4, 1, 2, 8, 7]
for i in range(len(nums), 0, -1): # 更新本趟遍历确定的元素位置
# flag用于标记是否有元素交换发生
flag = 0
for j in range(i - 1): # 遍历未排序的数组
if nums[j] > nums[j + 1]:
nums[j], nums[j + 1] = nums[j + 1], nums[j]
flag = 1 # 标记存在元素交换
if not flag:
break # 如果本趟遍历没有发生元素交换,直接跳出循环
print(nums)
4.归并排序
思路:
先把数列拆分为子数列,对子数列进行排序后,再把有序的子数列合并为完整的有序数列
# 归并排序
nums = [5, 3, 6, 4, 1, 2, 8, 7]
def MergeSort(num):
if len(num) <= 1: # 递归边界条件
return num # 到达边界时返回当前的子数组
mid = int(len(num) / 2) # 求出数组的中位数
llist, rlist = MergeSort(num[:mid]), MergeSort(num[mid:]) # 调用函数分别为左右数组排序
result = []
i, j = 0, 0
while i < len(llist) and j < len(rlist): # while循环用于合并两个有序数组
if rlist[j] < llist[i]:
result.append(rlist[j])
j += 1
else:
result.append(llist[i])
i += 1
result += llist[i:] + rlist[j:] # 把数组未添加的部分加到结果数组末尾
return result # 返回已排序的数组
print(MergeSort(nums))
5.快速排序
思路:
取数组中的一个数作为基准值,把所有小于基准值的数都放在它的一侧,再把所有大于基准值的数都放在它的另一侧。随后,对基准值左右两侧的数组分别进行快速排序。
一般情况下,取数组的第一个数作为基准进行快速排序。
(1)移动右边的指针,一直到指针指向的元素小于基准值为止,把右边的指针指向的值2赋给左边的指针指向的位置,这时候,原来2所在的位置实际上是空出来的空位。
(2)移动左边的指针,等到它指向了一个大于等于基准值的数再停下。类似地,把左边的指针指向的值赋给右边的指针指向的位置。左边指针指向的位置成为空位。
(3)重复以上步骤,直到左指针和右指针重合,左指针和右指针共同指向的位置就是基准值在有序数组中的位置,它的值大于它左侧的所有元素,并小于等于它右侧的所有元素(如果有相等的元素出现)。
(4)剩余的步骤为递归地排序左右子数组,直到全部数组排序完毕。
nums = [5, 3, 6, 4, 1, 2, 8, 7]
def QSort(left, right):
# 子数组第一个元素和最后一个元素在原数组中的位置
if left >= right: # 边界条件
return
l, r, key = left, right, nums[left] # 初始化左指针,右指针和基准值
while l < r: # 调整元素位置
while l < r and nums[r] >= key:
r -= 1
nums[l] = nums[r]
while l < r and nums[l] < key:
l += 1
nums[r] = nums[l]
nums[l] = key # 把基准值赋给左指针和右指针共同指向的位置
QSort(left, l - 1) # 左侧数组排序
QSort(l + 1, right) # 右侧数组排序
QSort(0, len(nums) - 1)
print(nums)
6.希尔排序
思路:
把数组内的元素按下标增量分组,对每一组元素进行插入排序后,缩小增量并重复之前的步骤,直到增量到达1
(1)使用(数组长度/2)作为初始增量,从第一个元素开始,以增量4来分组。
(2)继续用相同的方法分组,对组内的元素进行插入排序使得它们有序。
整个数组内的数都被遍历完成后,这一轮排序就结束了。
(3)把增量缩小一半,继续进行下一轮排序。增量为2时,可以看出每一组内的元素增多了,组的总数减少了。继续对每一组内的元素进行插入排序,直到每一组都遍历完成。
(4)再次把增量缩小一半;这时增量为1,相当于对整个数组进行插入排序,也就是最后一轮排序。
nums = [5, 3, 6, 4, 1, 2, 8, 7]
def ShellSort(nums):
step = len(nums) // 2 # 初始化增量为数组长度的一半
while step > 0: # 增量必须是大于0的整数
for i in range(step, len(nums)):
# 遍历需要进行插入排序的数
ind = i
while ind >= step and nums[ind] < nums[ind - step]: # 对每组进行插入排序
nums[ind], nums[ind - step] = nums[ind - step], nums[ind]
ind -= step
step //= 2 # 增量缩小一半
print(nums)
ShellSort(nums)