資料結構與演算法系列10 排序演算法 歸併 快排

2021-08-29 20:16:09 字數 3088 閱讀 5570

思想:

歸併排序的核心思想還是蠻簡單的。如果要排序乙個陣列,我們先把陣列從中間分成前後兩部分,然後對前後兩部分分別排序,再將排好序的兩部分合併在一起,這樣整個陣列就都有序了。

#歸併排序

def merge_sort(a):

n=len(a)

merge_sort_between(a,0,n-1)

def merge_sort_between(a,low,high):

#遞迴終止條件

if low>=high:

return

#獲取p到r之間的中間位置min

min=(high+low)//2

#分治遞迴排序,分成兩個部分

merge_sort_between(a,low,min)

merge_sort_between(a,min+1,high)

#將分治的兩個陣列合併,即將a[low...min]和a[min+1..high]合併

merge(a,low,high,min)

#合併函式

def merge(a,low,high,min):

#用兩個游標 i 和 j,分別指向 a[low…min] 和 a[min+1…high] 的第乙個元素

i,j=low,min+1

tmp=

while i<=min and j<=high:

if a[i]<=a[j]:

i+=1

else:

j+=1

#判斷哪個子陣列中有剩餘的資料

start = i if i <= min else j

end = min if i <= min else high

#將剩餘的資料拷貝到臨時陣列tmp

tmp.extend(a[start:end+1])

#將tmp中的陣列拷貝回a[low...high]

a[low:high+1] = tmp

a1 = [3, 5, 6, 7, 8]

a2 = [2, 2, 2, 2]

a3 = [4, 3, 2, 1]

a4 = [5, -1, 9, 3, 7, 8, 3, -2, 9]

aa=[6,4,7,8,2,1,4,1]

merge_sort(aa)

print(aa)

第一,歸併排序是穩定的排序演算法嗎?

歸併排序是乙個穩定的排序演算法。

第二,歸併排序的時間複雜度是多少?

歸併排序的執行效率與要排序的原始陣列的有序程度無關,所以其時間複雜度是非常穩定的,不管是最好情況、最壞情況,還是平均情況,時間複雜度都是o(nlogn)。

第三,歸併排序是原地排序演算法嗎?空間複雜度是多少?

歸併排序不是原地排序演算法,這是因為歸併排序的合併函式,在合併兩個有序陣列為乙個有序陣列時,需要借助額外的儲存空間。它的空間複雜度是o(n)。

思想:如果要排序陣列中下標從p到r之間的一組資料,我們選擇p到r之間的任意乙個資料作為pivot(分割槽點)。我們遍歷p到r之間的資料,將小於pivot的放到左邊,將大於pivot的放到右邊,將pivot放到中間。經過這一步驟之後,陣列p到r之間的資料就被分成了三個部分,前面p到q-1之間都是小於pivot的,中間是pivot,後面的q+1到r之間是大於pivot的。

from typing import list

import random

def quick_sort(a: list[int]):

_quick_sort_between(a, 0, len(a)-1)

def _quick_sort_between(a: list[int], low: int, high: int):

if low >= high: return

# get a random position as the pivot

k = random.randint(low, high)

a[low], a[k] = a[k], a[low]

m = _partition(a, low, high) # 獲取分割槽點

_quick_sort_between(a, low, m-1)

_quick_sort_between(a, m+1, high)

def _partition(a: list[int], low: int, high: int):

pivot, j = a[low], low #pivot用來儲存我們的分割槽點的值,j為最終我們分割槽點的下標

for i in range(low+1, high+1):

if a[i] <= pivot:

j += 1

a[j], a[i] = a[i], a[j] # swap

a[low], a[j] = a[j], a[low] #將我們的分割槽值(也就是第乙個位置的值)放到對應的分割槽下標(j)下面

return j

if __name__ == "__main__":

a1 = [3, 5, 6, 7, 8]

a2 = [2, 2, 2, 2]

a3 = [4, 3, 2, 1]

a4 = [5, -1, 9, 3, 7, 8, 3, -2, 9]

quick_sort(a1)

print(a1)

第一,快速排序是穩定的排序演算法嗎?

快速排序並不是乙個穩定的排序演算法

第二,快速排序的時間複雜度是多少?

最好時間複雜度、平均時間複雜度:o(nlogn),最壞時間複雜度:o(n2)。

第三,快速排序是原地排序演算法嗎?

是歸併排序演算法是一種在任何情況下時間複雜度都比較穩定的排序演算法,這也使它存在致命的缺點,即歸併排序不是原地排序演算法,空間複雜度比較高,是+o(n)。正因為此,它也沒有快排應用廣泛。

快速排序演算法雖然最壞情況下的時間複雜度是o(n2),但是平均情況下時間複雜度都是o(nlogn)。不僅如此,快速排序演算法時間複雜度退化到o(n2)+的概率非常小,我們可以通過合理地選擇pivot來避免這種情況。

資料結構和演算法系列(3)排序演算法

使用場景 o n n n 1 2 如果n比較小的話它的時間複雜度就會降級 資料量比較小,常見於小遊戲中10個左右資料的排序場景 具體實現 氣泡排序演算法 適用於資料量比較小的場景 param array public static void bubblesort int array if flag ...

資料結構系列 一 排序演算法

1.2 插入排序 1.3 選擇排序 1.4 歸併排序 1.5 堆排序 1.6 快速排序 基於資料狀況的排序演算法 1.7桶排序 1.8 小結 穩定排序 相對次序並沒有改變 void bubblesortv1 int a,int n 實現 增加乙個sorted標誌,對於有序陣列則不再進行比較判斷。複雜...

演算法系列之 2 排序演算法簡介

簡介 在演算法的世界裡,排序是最基本又是最重要的一類。在tacp the art of computing programming 中,佔據了專門且重要的篇幅。在面試中也是屢屢出現。一般而言,排序是查詢的基礎,比如著名的二分查詢,就是建立在有序序列的基礎上的。在眾多的排序演算法中,可以按照時間複雜度...