排序和查找
一、知識概覽
本章主要講解六種排序算法中的歸併排序和快速排序,知識概覽如下。
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]