03 排序演算法

2022-07-15 21:12:18 字數 3108 閱讀 3761

直接移動 ( 交換資料位置 )

邏輯移動 ( 改變指標,更快 )

jmp = len(data) // 2

while jmp != 0:

# 插入排序

for i in range(jmp, len(data)):

tmp = data[i]

j = i - jmp

while j >= 0 and tmp < data[j]:

data[j + jmp] = data[j]

j -= jmp

data[j + jmp] = tmp

jmp = jmp // 2

合併排序法( merge sort )

針對以排好序的兩個或兩個以上的數列(或資料檔案),通過合併的方式,將其組合成乙個大的且已排好序的數列(或資料檔案)。

2 路( 2-way )合併排序:

① 將 n 個長度為 1 的鍵值,成對的合併成 n/2 個長度為 2 的有序鍵值組

② 將 n/2 個長度為 2 的鍵值組,成對的合併成 n/4 個長度為 4 的有序鍵值組

③ 不斷合併,直到鍵值組長度為 n,且已排好序

l3 = 

idx1 = idx2 = 0

for i in range(len(l1) + len(l2)-2):

if l1[idx1] < l2[idx2]:

idx1 += 1

if idx1 == len(l1):

l3.extend(l2[idx2:])

break

else:

idx2 += 1

if idx2 == len(l2):

l3.extend(l1[idx1:])

break

快速排序法( quick sort ) / 分割交換排序法

目前公認最佳。使用了分而治之( divide and conquer )。

先在資料中找到乙個虛擬的中間值,並按此中間值將所有打算排序的資料分為兩部分。小於中間值的再左邊,大於的再右邊。再以同樣的方式分別處理左、右兩邊資料,直到排完序為止。

假設有 n 項記錄 r1,r2,r3,...,rn,其鍵值為 k1, k2,k3,...,kn:

① 先假設 k 的值為第乙個鍵值

② 從左向右找出鍵值 ki,使得 ki > k

③ 從右向左找出鍵值 kj,是的 kj < k

④ 如果 i < j,那麼 ki 與 kj 互換,並回到步驟 ②

⑤ 若 i ≥ j,則將 k 與 kj 互換,並以 j 為基準點分割成左右兩部分。然後針對左右兩部分進行步驟 ① 至 ⑤,直到左半邊鍵值等於右半邊鍵值

def quick(d, size, lf, rg):

# 第一項鍵值為 d[lf]

# size = len(d)

if lf < rg: # 左右兩邊索引值

# ②lf_idx = lf + 1

while d[lf_idx] < d[lf]:

if lf_idx + 1 == size:

break

lf_idx += 1

# ③rg_idx = rg

while d[rg_idx] > d[lf]:

rg_idx -= 1

# ④while lf_idx < rg_idx:

d[lf_idx], d[rg_idx] = d[rg_idx], d[lf_idx]

lf_idx += 1

while d[lf_idx] < d[lf]:

lf_idx += 1

rg_idx -= 1

while d[rg_idx] > d[lf]:

rg_idx -= 1

# ⑤d[lf], d[rg_idx] = d[rg_idx], d[lf]

quick(d, size, lf, rg_idx-1) # 以rg_idx為基準點分成左右兩半,以遞迴方式分別為左右兩邊進行排序直至完成排序

quick(d, size, rg_idx+1, rg)

基數排序法

並不需要元素間進行比較,屬於一種分配模式排序方式。

按比較的方向可分為最高位優先 ( most significant digit first , msd ) 和最低位優先 ( least significant digit first , lsd ) 兩種。

msd 是從最左邊的位數開始比較,lsd 是從最右邊的位數開始比較。

def radix(data):

"""0~999 整數比較"""

n = 1 # n 為基數,從個位開始排序

while n <= 100:

tmp = [[none] * 100 for row in range(10)] # 設定暫存陣列 [[n位為0的所有元素], [?1], [?2], ... , [?9]]。

for i in range(len(data)):

m = (data[i] // n) % 10 # n 位的數值,n=1為個位,n=10為10位

tmp[m][i] = data[i] # 放入棋盤對應位置

k = 0

for i in range(10):

for j in range(len(data)):

if tmp[i][j] is not none:

data[k] = tmp[i][j] # 讀出棋盤裡的值,重構陣列

k += 1

n *= 10

原陣列 [3, 5, 32, 74, 169, 2, 111, 0]

過程:比較個位 [0, 111, 32, 2, 3, 74, 5, 169]

比較十位 [0, 2, 3, 5, 111, 32, 169, 74]

比較百位 [0, 2, 3, 5, 32, 74, 111, 169]

結果:[0, 2, 3, 5, 32, 74, 111, 169]

冒泡、選擇、插入排序三種資料搬移量最大的是 插入排序。

合併排序法是穩定的。不會改變兩個相同數字的原有順序。

練習03 排序

a題 big number 題意 求階乘n的結果又多少位數。poj的資料比hdu難過點,但是hdu討論版的斯特林公式可以。我也不會證明,只能抄下來了咯。include include include include include define max 10000005 using namespac...

03 排序 氣泡排序

基本原理 顧名思義就是整個過程向氣泡一樣往上公升,單向氣泡排序的基本原理就是 對於給定的n個資料,從第乙個資料開始一次對相鄰的兩個記錄進行比較,當前面的記錄大於後面的記錄時,交換位置,進行一輪比較和換位後,n個記錄中最大的那個被排在最後,即第n位。然後對前面n 1個記錄進行第二次比較,重複該過程。實...

演算法 排序1 排序

題目 給定n個 長整型範圍內的 整數,要求輸出從小到大排序後的結果。本題旨在測試各種不同的排序演算法在各種資料情況下的表現。各組測試資料特點如下 輸入第一行給出正整數n 10 5 隨後一行給出n個 長整型範圍內的 整數,其間以空格分隔。在一行中輸出從小到大排序後的結果,數字間以1個空格分隔,行末不得...