参考:https://www.cnblogs.com/onepixel/articles/7674659.html
希尔排序(Shell Sort)
时间复杂度(平均): O(n^log2n) 时间复杂度(最坏): O(n^2) 时间复杂度(最好):O(n) 空间复杂度:O(1) 稳定性:不稳定
算法描述
先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,具体算法描述:
- 选择一个增量序列t1,t2,…,tk,其中ti>tj,tk=1;
- 按增量序列个数k,对序列进行k 趟排序;
- 每趟排序,根据对应的增量ti,将待排序列分割成若干长度为m 的子序列,分别对各子表进行直接插入排序。仅增量因子为1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。
代码
'''
希尔排序
算法原理:分组,span = len(nums)/2 (可以理解为组数),依次对每组中元素(跨度为span)插入排序; 然后span/2 重复上述排序
跨度为span的一组一组元素为排序结果 (因为采用了跨度,保证了插入排序的平均复杂度较小,从而降低希尔排序的时间复杂度)
'''
def sort(nums):
span = int(len(nums)/2)
while span > 0:
for i in range(span, len(nums), 1):
temp = nums[i]
j = i
while temp < nums[j -span] and j - span > -1:
nums[j] = nums[j - span]
j = j - span
nums[j] = temp
span = int(span/2)
def sort1(nums):
# 按分组去算,比较繁琐,且比较绕
if len(nums)==1:
return nums
span = int(len(nums)/2) # 分组个数
while span > 0:
n = int(len(nums)/span) # 组内数
for i in range(span + 1):
for j in range(1, n, 1):
if (j * span + i) > len(nums) - 1:
break
for k in range(j-1, -1, -1):
if nums[k * span + i] > nums[j * span + i]:
temp = nums[k * span + i]
nums[k * span + i] = nums[j * span + i]
nums[j * span + i] = temp
span = int(span/2)
归并排序(Merge Sort)
时间复杂度(平均): O(nlog2n) 时间复杂度(最坏):O(nlog2n) 时间复杂度(最好):O(nlog2n) 空间复杂度:O(n) 稳定性:稳定
算法描述
- 把长度为n的输入序列分成两个长度为n/2的子序列;
- 对这两个子序列分别采用归并排序;
- 将两个排序好的子序列合并成一个最终的排序序列。
代码
'''
归并排序
采用递归的方法, 长度小于一的数组,直接返回;长度为二的数组,两者比较返回;长度大于三,切分左右两部分,分别递归调用归并排序算法,得到排好序的左边数组和右边数组,然后遍历两个数组,进行排序。
分块为排序好的数组
'''
def merge_sort(nums):
if len(nums)<=1:
return nums
if len(nums)==2:
if nums[0] > nums[1]:
temp = nums[0]
nums[0] = nums[1]
nums[1] = temp
return nums
half = int((len(nums) + 1)/2)
left = merge_sort(nums[:half])
right = merge_sort(nums[half:])
res = []
i, j = 0, 0
# while i < len(left) or j < len(right):
# if i == len(left): # 这里每次需要再判断,实际上如果知道剩余的是right或者left,之后直接加入到res即可,不需要再判断
# res.append(right[j])
# j += 1
# elif j == len(right):
# res.append(left[i])
# i += 1
# elif left[i] <= right[j]:
# res.append(left[i])
# i += 1
# else:
# res.append(right[j])
# j += 1
while i < len(left) and j < len(right): # 这种逻辑也可以直接判断 if j == len(right): res += left[i:] if i == len(left): res += left[j:]
if left[i] <= right[j]:
res.append(left[i])
i += 1
else:
res.append(right[j])
j += 1
while i < len(left):
res.append(left[i])
i += 1
while j < len(right):
res.append(right[j])
j += 1
return res