排序演算法Python(冒泡、選擇、快速、插入、希爾、歸併排序)
排序演算法Python(冒泡、選擇、快速、插入、希爾、歸併排序)
排序有內部排序和外部排序,內部排序是資料記錄在記憶體中進行排序,而外部排序是因排序的資料很大,一次不能容納全部的排序記錄,在排序過程中需要訪問外存。
我們通常所說的排序演算法往往指的是內部排序演算法,即資料記錄在記憶體中進行排序。內部排序的分類:
一種是比較排序,時間複雜度O(nlogn) ~ O(n^2),主要有:氣泡排序,選擇排序,快速排序,插入排序,希爾排序,歸併排序,堆排序等。
另一種是非比較排序,時間複雜度可以達到O(n),主要有:計數排序,基數排序,桶排序等。
常見排序演算法的一些特性:
氣泡排序
通過上面的動圖也可以看出來,冒泡通過兩重迴圈遍歷每一個數後將最大的’冒’出去
冒泡是相鄰元素之間的比較,每次把最大的’冒’出去
由於需要經過兩重迴圈,所以時間複雜度為:O(n2)
選擇排序
選擇排序相比氣泡排序不穩定,時間複雜度也是。
選擇排序沒趟都會產生最小值,它不是相鄰元素的比較而是在該元素設定一個索引i。
然後與陣列的其他元素依次比較(除了上一個索引值),直到找到小於該元素(索引j)時交換兩元素,
接著繼續從i索引(此時已經不是原來的數值)值與索引j+1值比較。重複上述比較過程:
冒泡是相鄰元素比較,選擇不是相鄰元素比較
選擇排序是把最小的選出來
快速排序
(1) 從數列中挑出一個基準值。
(2) 將所有比基準值小的擺放在基準前面,所有比基準值大的擺在基準的後面(相同的數可以到任一邊);在這個分割槽退出之後,該基準就處於最終它應該在的地方。
(3) 遞迴地把”基準值前面的子數列”和”基準值後面的子數列”進行排序。
快速排序的時間複雜度在最壞情況下是O(N2),平均的時間複雜度是O(N*lgN)。
假設有如下陣列,將兩個哨兵設在左右端,最左端的值為基準
1.右邊向左運動,直到找到一個比基準小的數
2.左邊向右運動,直到找到一個比基準大的數
3.交換兩個數
4.如果兩個哨兵不相遇,則繼續上述步驟
5.相遇之後和基準交換
這樣‘6’就永遠在它最終應該待的地方了,對6的前一半和後一半進行上述完整操作即可(遞迴)
插入排序
(1) 初始時,a[0]自成1個有序區,無序區為a[1..n-1]。令i=1
(2) 將a[i]併入當前的有序區a[0…i-1]中形成a[0…i]的有序區間。
(3) i++並重復第二步直到i==n-1。排序完成。
直接插入排序的時間複雜度是O(n2)
希爾排序
是插入排序的一種更高效的改進版本。希爾排序是非穩定排序演算法。分組的插入排序
先將整個待排元素序列分割成若干個子序列(由相隔某個“增量”的元素組成的)分別進行直接插入排序,然後依次縮減增量再進行排序,待整個序列中的元素基本有序(增量足夠小)時,再對全體元素進行一次直接插入排序。因為直接插入排序在元素基本有序的情況下(接近最好情況),效率是很高的,因此希爾排序在時間效率上比前兩種方法有較大提高。
如排序資料為[ 5 9 7 2 3 1 6 ],那麼資料長度為7
第一次分割gap=7/2=3
i和j之間總是間隔gap個單位,其中j從gap遍歷到資料中的最後一個數,j=i-gap
如上圖,最後一次交換時j−gap>=0,但在這裡沒有什麼影響,下面將看出使用j−gap的作用
第二次分割gap=3/2=1
當分割的間隔是1的時候,首先交換前兩個的值,當j和i分別移到3和1的時候,首先交換,因為3>1,然後應該往前迭代,即j−=gap,否則的話我們只比較了3和1,而實際上最前面的2也是大於1的,也應該交換。
如此往復,我們就會得到最終的排序結果。
歸併排序
是分治法的一種,上圖可以清晰的描述排序過程
先拆分(遞迴),後合併
效率為 O(n log n)
Python的實現
'''
氣泡排序
重複走訪過要排序的序列,一次比較兩個元素,如果他們的順序錯誤就將他們進行交換,一次冒上來的是最小的,其次是第二小。
時間複雜度:O(n^2)
空間複雜度:O(1)
穩定性:穩定
'''
def BubbleSort(data):
for i in range(len(data)):
for j in range(len(data)-i-1):
if data[j]>data[j+1]:
data[j+1] , data[j] = data[j] , data[j+1]
'''
選擇排序
選擇排序相比氣泡排序不穩定,時間複雜度也是。選擇排序沒趟都會產生最小值,它不是相鄰元素的比較而是在該元素設定一個索引i。
然後與陣列的其他元素依次比較(除了上一個索引值),直到找到小於該元素(索引j)時交換兩元素,
接著繼續從i索引(此時已經不是原來的數值)值與索引j+1值比較。重複上述比較過程……簡單的原理圖如下:
冒泡是相鄰元素比較,選擇不是相鄰元素比較
'''
def SelectionSort(data):
for i in range(len(data)):
for j in range(i+1,len(data)):
if data[j]<data[i]:
data[i] , data[j] = data[j] , data[i]
'''
快速排序
快速排序流程:
(1) 從數列中挑出一個基準值。
(2) 將所有比基準值小的擺放在基準前面,所有比基準值大的擺在基準的後面(相同的數可以到任一邊);在這個分割槽退出之後,該基準就處於最終它應該在的地方。
(3) 遞迴地把"基準值前面的子數列"和"基準值後面的子數列"進行排序。
快速排序的時間複雜度在最壞情況下是O(N2),平均的時間複雜度是O(N*lgN)。
'''
def QuickSort(lists, left, right):
# 快速排序
if left >= right:
return lists
key =left
low = left
high = right
while left < right:
while left < right and lists[right] >= lists[key]:#如果右邊比基準小,停下
right -= 1
while left < right and lists[left] <= lists[key]:#如果左邊比基準大,停下
left += 1
lists[right],lists[left]=lists[left],lists[right]#交換現在的左右值
lists[right] ,lists[key]=lists[key],lists[right] #left和right匯合後和基準交換
print_data(data)#交換過程
QuickSort(lists, low, left - 1)
QuickSort(lists, left + 1, high)
return lists
'''
直接插入排序
1. 初始時,a[0]自成1個有序區,無序區為a[1..n-1]。令i=1
2. 將a[i]併入當前的有序區a[0…i-1]中形成a[0…i]的有序區間。
3. i++並重復第二步直到i==n-1。排序完成。
直接插入排序的時間複雜度是O(N2)。
假設被排序的數列中有N個數。遍歷一趟的時間複雜度是O(N),需要遍歷多少次呢?N-1!因此,直接插入排序的時間複雜度是O(N2)。
'''
def InsertionSort(data):
for i in range(1,len(data)):
key=data[i]
j=i-1
while j>=0:
if data[j]>key:
data[j+1]=data[j]
data[j]=key
j-=1
'''
希爾排序
是插入排序的一種更高效的改進版本。希爾排序是非穩定排序演算法。分組的插入排序
j-=gap第一次交換資料後,看它是後面的數否還小於前面的數
如2 3 1 5 9 6這個序列以1位步長的話
一次交換後2 1 3 5 9 6此時j指向第二個數,i指向第三個數
所以交換後應該用j-gap往前檢視是否前面的更小
'''
def ShellSort(data):
gap=int(len(data)/2) #排序的分組
while gap>0:
for i in range(gap,len(data)):
j=i-gap
while data[j]>data[i] and j >=0:
data[j],data[i]=data[i],data[j]
j-=gap
i-=gap
gap=int(gap/2)
'''
歸併排序
先拆分,後合併
'''
def MergeSort(ls):
if len(ls)<2:
return ls
mid = len(ls) >> 1 #相當於除2取整
left = MergeSort(ls[:mid])
right = MergeSort(ls[mid:])
return merge(left,right)
def merge(left, right):
result = []
i, j = 0, 0
while i < len(left) and j < len(right):
if left[i] < right[j]:
result.append(left[i])
i += 1
else:
result.append(right[j])
j += 1
result += left[i:]
result += right[j:]
return result
'''列印函式'''
def print_data(data):
for i in data:
print(i,end=' ')
print()
'''測試程式碼'''
data=[5,9,7,2,3,1,6]
BubbleSort(data)
print_data(data)
data=[5,9,7,2,3,1,6]
SelectionSort(data)
print_data(data)
data=[5,9,7,2,3,1,6]
QuickSort(data,0,6)
print_data(data)
data=[5,9,7,2,3,1,6]
InsertionSort(data)
print_data(data)
data=[5,9,7,2,3,1,6]
ShellSort(data)
print_data(data)
data=[5,9,7,2,3,1,6]
data=MergeSort(data)
print_data(data)
轉載:http://blog.csdn.net/qq_33414271/article/details/78528891 感謝博主分享
相關文章
- 七、排序,選擇、冒泡、希爾、歸併、快速排序實現排序
- (建議收藏)2020最新排序演算法總結:冒泡、選擇、插入、希爾、快速、歸併、堆排序、基數排序排序演算法
- Python八大演算法的實現,插入排序、希爾排序、氣泡排序、快速排序、直接選擇排序、堆排序、歸併排序、基數排序。Python演算法排序
- 排序演算法(氣泡排序,選擇排序,插入排序,希爾排序)排序演算法
- 排序演算法 - 快速插入排序和希爾排序排序演算法
- 【排序】插入類排序—(折半)插入排序、希爾排序排序
- php插入排序,快速排序,歸併排序,堆排序PHP排序
- 排序法:選擇、冒泡、插入和快排排序
- 幾大排序總結(上)!圖解解析+程式碼例項(冒泡、選擇、插入、希爾、快排)排序圖解
- 排序演算法__希爾排序排序演算法
- 【排序演算法】- 希爾排序排序演算法
- 單連結串列的排序(插入,選擇,冒泡)排序
- 三種插入排序 直接插入排序,折半插入排序,希爾排序排序
- 快速排序&&歸併排序排序
- 【資料結構與演算法】高階排序(希爾排序、歸併排序、快速排序)完整思路,並用程式碼封裝排序函式資料結構演算法排序封裝函式
- 基礎排序(冒泡、選擇、插入)學習筆記排序筆記
- 四、歸併排序 && 快速排序排序
- 最簡單易懂的三種排序演算法:冒泡、選擇、插入排序演算法
- python實現希爾排序演算法Python排序演算法
- PHP 排序演算法之希爾排序PHP排序演算法
- 【PHP資料結構】插入類排序:簡單插入、希爾排序PHP資料結構排序
- PHP 常見4種排序 氣泡排序、選擇排序、插入排序、快速排序PHP排序
- 桶排序 選擇,插入排序排序
- 演算法之常見排序演算法-氣泡排序、歸併排序、快速排序演算法排序
- 排序演算法:Java實現希爾排序排序演算法Java
- 常見的排序演算法:冒泡、快排、歸併排序演算法
- 排序演算法__歸併排序排序演算法
- 排序演算法:歸併排序排序演算法
- 排序演算法 - 歸併排序排序演算法
- 排序演算法(歸併排序)排序演算法
- 歸併排序--排序演算法排序演算法
- 希爾排序排序
- Python排序演算法之 選擇排序Python排序演算法
- 反射,hashlib模組,正則匹配,冒泡,選擇,插入排序反射排序
- php實現 歸併排序,快速排序PHP排序
- 選擇排序和快速排序排序
- 前端也能學演算法:JS版常見排序演算法-冒泡,插入,快排,歸併前端演算法JS排序
- 排序演算法之 '歸併排序'排序演算法
- python實現氣泡排序、插入排序以及快速排序演算法Python排序演算法