希尔排序
希尔排序使用增量i(有时称为 gap ),通过选择 i 个项的所有项来创建子列表。对子列表进行差值排序,最后进行一次插值排序
子列表插值排序
全局插值排序
归并排序
归并排序是一种递归算法,不断将列表拆分为一半。 如果列表为空或有一个项,则按定义(基本情况)进行排序。如果列表有多个项,我们分割列表,并递归调用两个半部分的合并排序。 一旦对这两半排序完成,就执行称为合并的基本操作。合并是获取两个较小的排序列表并将它们组合成单个排序的新列表的过程。
#递归基本条件递归基本条件
alist = [54,26,93,17,77,31,44,55,20]
#归并算法 递归拆分
def mergeSort(alist):
if len(alist) == 1: #递归基本条件 一个元素不需要排序
return alist
elif len(alist) == 2: #递归基本条件 数组被划分为2长度的数组,较小的排前面
return [alist[0],alist[1]] if alist[0] < alist[1] else [alist[1],alist[0]]
else:
return_list = []
middle = len(alist)//2
left = mergeSort(alist[:middle])
right = mergeSort(alist[middle:])
#对递归后的左右子数组进行排序,比较头部元素,小的弹出,直至一方长度为0
while len(left) > 0 and len(right) >0:
if left[0] < right[0]:
return_list.append(left.pop(0))
elif left[0] > right[0]:
return_list.append(right.pop(0))
else:
return_list.append(left.pop(0))
return_list.append(right.pop(0))
return_list = return_list + (left if len(left) > 0 else right)
return return_list
print(alist)
列表被分成两半。我们已经计算过(在二分查找中)将列表划分为一半需要 log^n 次,其中 n 是列表的长度。第二个过程是合并。列表中的每个项将最终被处理并放置在排序的列表上。因此,大小为 n 的列表的合并操作需要 n 个操作。此分析的结果是 log^n 的拆分,其中每个操作花费n,总共 nlog^n 。归并排序是一种 O(nlogn) 算法。
mergeSort 函数需要额外的空间来保存两个半部分,因为它们是使用切片操作提取的。如果列表很大,这个额外的空间可能是一个关键因素,并且在处理大型数据集时可能会导致此类问题。
快速排序
快速排序使用分而治之来获得与归并排序相同的优点,而不使用额外的存储。然而,作为权衡,有可能列表不能被分成两半。当这种情况发生时,我们将看到性能降低。
快速排序首先选择一个值,该值称为 枢轴值 。虽然有很多不同的方法来选择枢轴值,我们将使用列表中的第一项。枢轴值的作用是帮助拆分列表。枢轴值属于最终排序列表(通常称为拆分点)的实际位置,将用于将列表划分为快速排序的后续调用。
#选定一个锚值,其余部分与其作比较,最后分为大于锚值和小于锚值的部分
alist = [54,54,93,17,77,31,34,54,20]
#alist要进行排序的列表 first,锚之后的元素,last,初始值为alist最后一个元素索引
def quickSort(alist,first,last):
anchor = first #锚值
alast = last
first = first + 1 #锚值下一个值
if last > len(alist) -1: #出界
return
elif first > last: #因为first +1 这里包含相等
return
elif last == first: #应为first+1,这里处理两个值的摆放顺序
if alist[anchor] > alist[last]:
temp = alist[anchor]
alist[anchor] = alist[last]
alist[last] = temp
return
while first < last: #循环结束条件
if alist[first] < alist[anchor] and alist[last] <= alist[anchor]: #左右均小于锚值,右不动,左进一,等于锚的值按大于处理
first = first + 1
elif alist[first] >= alist[anchor] and alist[last] < alist[anchor]: #左大于锚,右小于锚,左右互换,等于锚的值按大于处理
temp = alist[first]
alist[first] = alist[last]
alist[last]= temp
first = first + 1
last = last - 1
elif alist[first] < alist[anchor] and alist[last] >= alist[anchor]: #左小右大,不用调整
first = first + 1
last = last - 1
elif alist[first] > alist[anchor] and alist[last] >= alist[anchor]: #左右都大,右边前移,寻找小的值进行互换
if alist[last] < alist[first]: # 这两个都大于锚的值可以比较后进行顺序调整,便于将较大值右移
temp = alist[first]
alist[first] = alist[last]
alist[last] = temp
last = last - 1
if first - anchor > 1: #first变化过说明有小于锚值的数,需要置换
if first - last == 1: #这种情况例如 13 10 20 这样,first最后会指向20,last指向10,但是first确实曾经小于锚值,需要置换
first = first -1
temp = alist[first]
alist[first] = alist[anchor]
alist[anchor] = temp
quickSort(alist,anchor,first-1)
quickSort(alist,first+1,alast)
quickSort(alist,0,len(alist)-1)
print(alist)