排序和查找
一、知识概览
本章主要讲解六种排序算法中的归并排序和快速排序,知识概览如下。
1.1 归并排序
1.2 快速排序
归并排序的重点在于合,而快速排序的重点在于分,下面是分裂过程:
二 代码实现
2.1 归并排序
#归并排序
def mergeSort(alist):
if len(alist)>1:
mid =len(alist)//2
lefthalf=alist[:mid]
righthalf=alist[mid:]
mergeSort(lefthalf)
mergeSort(righthalf)
i=j=k=0
while i<len(lefthalf) and j<len(righthalf):
if lefthalf[i]<righthalf[j]:
alist[k]=lefthalf[i]
i=i+1
#拉链式交错把左右半部从小到大归并到结果列表中
else:
alist[k]=righthalf[j]
j=j+1
k=k+1
#归并左半部剩余项
while i<len(lefthalf):
alist[k]=lefthalf[i]
i=i+1
k=k+1
#归并右半部剩余项
while j<len(righthalf):
alist[k]=righthalf[j]
j=j+1
k=k+1
测试:
alist=[54,26,93,17,77,31,44,55,20]
mergeSort(alist)
print(alist)
输出:
[17, 20, 26, 31, 44, 54, 55, 77, 93]
2.2 更pythonic的归并排序
#更pythonic的归并排序
def mergeSort2(alist):
#递归结束条件
if len(alist)<=1:
return alist
#分解问题,并递归调用
middle=len(alist)//2
left=mergeSort2(alist[:middle])#左半部分排好序
right=mergeSort2(alist[middle:])#右半部分排好序
#合并左右半部分,完成排序
merged=[]
while left and right:#只要左右半部分都还有数据就进行合并
if left[0]<=right[0]:#左半部分首部和右半部分首部进行对比
merged.append(left.pop(0))#哪个小就添加到前面,同时把它删除掉
else:
merged.append(right.pop(0))
#循环后可能有剩也可能没有
merged.extend(right if right else left)#无论左右只要还有剩的,就归并到列表的后面
return merged
测试:
alist=[54,26,93,17,77,31,44,55,20]
mergeSort2(alist)
print(alist)
测试
alist = [54, 26, 93, 17, 77, 31, 44, 55, 20]
u=mergeSort2(alist)
print(u)
输出
[17, 20, 26, 31, 44, 54, 55, 77, 93]
2.3 快速排序
# 快速排序
def quickSort(alist):
quickSortHelper(alist, 0, len(alist) - 1)
def quickSortHelper(alist, first, last):
if first < last: # 基本结束条件
# 分裂
splitpoint = partition(alist, first, last)
quickSortHelper(alist, first, splitpoint - 1)
quickSortHelper(alist, splitpoint + 1, last)
def partition(alist, first, last):
# 选定中值
pivotvalue = alist[first]
# 左右标初值
leftmark = first + 1
rightmark = last
done = False
while not done:
while leftmark <= rightmark and alist[leftmark] <= pivotvalue:
leftmark = leftmark + 1
while leftmark <= rightmark and alist[rightmark] >= pivotvalue:
rightmark = rightmark - 1
if rightmark < leftmark:
done = True
else:
# 左右标值交换
temp = alist[leftmark]
alist[leftmark] = alist[rightmark]
alist[rightmark] = temp
# 中值就位
temp = alist[first]
alist[first] = alist[rightmark]
alist[rightmark] = temp
return rightmark # 中值点也是分裂点
alist = [54, 26, 93, 17, 77, 31, 44, 55, 20]
quickSort(alist)
print(alist)
输出
[17, 20, 26, 31, 44, 54, 55, 77, 93]