1 八大排序算法的時間復雜度和空間復雜度
排序算法 | 穩定性 | 平均時間復雜度 | 最差時間復雜度 | 空間復雜度 | 備注 |
---|---|---|---|---|---|
堆排序 | 不穩定 | O(nlogn) | O(nlogn) | O(1) | n大時較好 |
快速排序 | 不穩定 | O(nlogn) | O(n^2) | O(nlogn) | n較大時好 |
希爾排序 | 不穩定 | O(nlogn) | O(n^s) | O(1) | s時所選的分組 |
選擇排序 | 不穩定 | O(n^2) | O(n^2) | O(1) | n較小時較好 |
基數排序 | 穩定 | O(logRB) | O(logRB) | O(n) | B是真數(0--9),R是基數 |
冒泡排序 | 穩定 | O(n^2) | O(n^2) | O(1) | n小時較好 |
插入排序 | 穩定 | O(n^2) | O(n^2) | O(1) | 大部分已排序時較好 |
歸並排序 | 穩定 | O(nlogn) | O(nlogn) | O(1) | n大時較好 |
- 排序算法的穩定性
假定再待排序的記錄序列中,存在多個相同的關鍵字的記錄,若經過排序,這些記錄的相對次序保持不變,即在序列中,A1=A2,且A1字A2之前,而在排序后的序列中,A1任在A2之前,則稱這種排序算法是穩定的,否則成為不穩定的。
2 各排序算法的python實現
2.1 冒泡排序(穩定)
nums = [1,3,1,4,5,9,12,1,11,135,12,3,45,67,89,23]
def bubbleSort(arr):
n = len(arr)
for i in range(n):
for j in range(0,n-i-1):
if arr[j]>arr[j+1]:
arr[j],arr[j+1] = arr[j+1],arr[j]
return arr
bubbleSort(nums)
2.2 歸並排序(穩定)
def merge(list_left,list_right):
l,r = 0,0
new_list = []
while l < len(list_left) and r<len(list_right):
if list_left[l] <= list_right[r]:
new_list.append(list_left[l])
l += 1
else:
new_list.append(list_right[r])
r += 1
new_list += list_left[l:]
new_list += list_right[r:]
return new_list
def mergeSort(arr):
if len(arr) <= 1:
return arr
mid = len(arr)//2
list_left = mergeSort(arr[:mid])
list_right = mergeSort(arr[mid:])
return merge(list_left,list_right)
arr = [12,33,15,11,1,1334,122234]
res = mergeSort(arr)
print(res)
2.3 插入排序(穩定)
def insertSort(arr):
for i in range(len(arr)):
preIndex = i - 1
current = arr[i]
while preIndex >=0 and arr[preIndex] > current:
arr[preIndex+1]=arr[preIndex]
preIndex -=1
arr[preIndex+1] = current
return arr
nums = [1,4,7,2,5,8,3,6,9,0]
insertSort(nums)
2.4 基數排序 (穩定)
def radixSort(arr):
n = len(str(max(arr)))
for k in range(n):
bucket_list = [[] for i in range(10)]
for i in arr:
bucket_list[i//(10**k)%10].append(i)
arr = [j for i in bucket_list for j in i]
return arr
2.5 選擇排序 (不穩定)
算法流程:
首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。
再從剩余未排序元素中繼續尋找最小(大)元素,然后放到已排序序列的末尾。
重復第二步,直到所有元素均排序完畢。
def selectionSort(arr):
for i in range(len(arr)-1):
minIndex = i # 記錄最小數的索引
for j in range(i+1,len(arr)):
if arr[j]<arr[minIndex]:
minIndex = j
if i!= minIndex:
arr[i],arr[minIndex] = arr[minIndex],arr[i]
return arr
nums = [1,4,7,2,5,8,3,6,9,0]
selectionSort(nums)
2.6 快速排序 (不穩定)
def quickSort(arr,i,j):
if i >= j:
return []
pivot = arr[i] # 以第一個元素為基准
low = i
high = j
while i < j:
while i<j and arr[j]>=pivot:
j -= 1
arr[i] = arr[j]
while i<j and arr[i] <= pivot:
i += 1
arr[j] = arr[i]
arr[j] = pivot
quickSort(arr,low,i-1)
quickSort(arr,i+1,high)
return arr
2.7 希爾排序
def shellSort(arr):
n = len(arr)
gap = int(n/2)
while gap > 0:
for i in range(gap,n):
temp = arr[i]
j = i
while j >= gap and arr[j-gap] > temp:
arr[j] = arr[j-gap]
j -= gap
arr[j] = temp
gap = int(gap/2)
return arr
2.8 堆排序
堆排序(Heapsort)是指利用堆這種數據結構所設計的一種排序算法。堆積是一個近似完全二叉樹的結構,並同時滿足堆積的性質:即子結點的鍵值或索引總是小於(或者大於)它的父節點。堆排序可以說是一種利用堆的概念來排序的選擇排序。
def heapify(arr, n, i):
largest = i
l = 2 * i + 1 # left = 2*i + 1
r = 2 * i + 2 # right = 2*i + 2
if l < n and arr[i] < arr[l]:
largest = l
if r < n and arr[largest] < arr[r]:
largest = r
if largest != i:
arr[i],arr[largest] = arr[largest],arr[i] # 交換
# 此時largest位置的數字(也就是最開始輸入那個lis[i])處於待定狀態,需要在它所有根部中確定其位置
heapify(arr, n, largest)
def heapSort(arr):
n = len(arr)
# Build a maxheap.
for i in range(n, -1, -1):
# 先把堆調整好小根堆的狀態,在全堆中逐個調整每個數字的位置,調整的方法是在它所有根部中確定其位置
heapify(arr, n, i)
# 一個個交換元素
for i in range(n-1, 0, -1):
arr[i], arr[0] = arr[0], arr[i] # 交換
# 把新上來的0號安排到合適的位置上去,其中i指的是要調整的堆的范圍
heapify(arr, i, 0)