目前實現了冒泡排序、選擇排序、插入排序、希爾排序、歸併排序和快速排序等常見算法。
1. 冒泡排序
通過兩層循環實現排序,每輪內循環實現外層子序列中最大/最小值的浮出。
def bubbleSort(nums:list):
for i in range(len(nums)-1):
for j in range(i+1, len(nums)):
if nums[j] < nums[i]:
nums[i], nums[j] = nums[j], nums[i]
return nums
# 一種優化方案:若某輪內循環詞序不變提前退出
def bubbleSort2(nums:list):
exchange = True
for i in range(len(nums)-1):
if not exchange:
return nums
exchange = False
for j in range(i+1, len(nums)):
if nums[j] < nums[i]:
exchange = True
nums[i], nums[j] = nums[j], nums[i]
return nums
2. 選擇排序
冒泡排序的優化,迴避了每兩個數字對比後的交換過程,在每輪內循環中,只需記錄下子序列中最大值的位置,循環結束後再交換一次即可。
def selectionSort(nums:list):
for i in range(len(nums)-1):
smallIndex = i
for j in range(i+1, len(nums)):
if nums[j] < nums[smallIndex]:
smallIndex = j
nums[i], nums[smallIndex] = nums[smallIndex], nums[i]
return nums
3. 插入排序
效仿摸牌的插入過程,在實現時並未直接從空列表開始增長,而是在原有序列上進行臨接位置的騰挪。
def insertSort(nums:list):
for i in range(1, len(nums)):
value = nums[i]
index = i
while index > 0 and nums[index-1] > value:
nums[index] = nums[index-1]
index -= 1
if index != i:
nums[index] = value
return nums
4. 希爾排序
插入排序的優化,通過在分段子序列上不斷的進行插入排序,使得整個序列不斷有序。
def shellSort(nums:list):
sublistcount = len(nums) // 2
while sublistcount > 0:
for startpositon in range(sublistcount):
gapInsertSort(nums, startpositon, sublistcount)
print("After increment of size {}, the list is {}.".format(sublistcount, nums))
sublistcount //= 2
def gapInsertSort(alist, start, gap):
for i in range(start+gap, len(alist), gap):
currentValue = alist[i]
while i > 0 and alist[i-gap] > currentValue:
alist[i] = alist[i-gap]
i -= gap
alist[i] = currentValue
5. 歸併排序
利用分治思想,實現序列排序結果和一對子序列排序結果間的遞歸操作。注意在一對子序列排序的對比過程中,需要分別採用一個動態指針。
def mergeSort(nums:list):
if len(nums) > 1:
mid_index = len(nums) // 2
left_nums = nums[:mid_index] # 切片爲deep_copy
right_nums = nums[mid_index:]
mergeSort(left_nums)
mergeSort(right_nums)
i, j = 0, 0
while i < len(left_nums) and j < len(right_nums):
if left_nums[i] < right_nums[j]:
nums[i+j] = left_nums[i]
i += 1
else:
nums[i+j] = right_nums[j]
j += 1
if i == len(left_nums):
nums[i+j:] = right_nums[j:]
if j == len(right_nums):
nums[i+j:] = left_nums[i:]
6. 快速排序
同樣利用遞歸思想,每輪找到樞軸值的排序索引,並據此將序列分爲大於樞軸值的子序列和小於樞紐值的子序列。
def quickSort(nums:list):
quickSortIter(nums, 0, len(nums)-1)
def quickSortIter(nums, first, last):
if first < last:
left_marker = first+1
right_marker = last
pivot = nums[first]
while left_marker < right_marker:
while nums[left_marker] <= pivot and left_marker <= right_marker and left_marker < last:
left_marker += 1
while nums[right_marker] >= pivot and left_marker <= right_marker and right_marker > 0:
right_marker -= 1
if left_marker < right_marker: # 防止left_marker和right_marker交錯時發生錯誤交換
nums[left_marker], nums[right_marker] = nums[right_marker], nums[left_marker]
if nums[right_marker] < pivot:
nums[right_marker], nums[first] = pivot, nums[right_marker]
quickSortIter(nums, first, right_marker-1)
quickSortIter(nums, right_marker+1, last)