經典七大排序算法

經典排序算法在面試中占有很大的比重,也是基礎,為了未雨綢繆,在寒假里整理并用Python實現了七大經典排序算法,包括冒泡排序,插入排序,選擇排序,希爾排序,歸并排序,快速排序,堆排序。希望能幫助到有需要的同學。之所以用Python實現,主要是因為它更接近偽代碼,能用更少的代碼實現算法,更利于理解。

本篇博客所有排序實現均默認從小到大。

一、冒泡排序 BubbleSort

介紹:

冒泡排序的原理非常簡單,它重復地走訪過要排序的數列,一次比較兩個元素,如果他們的順序錯誤就把他們交換過來。

步驟:

  1. 比較相鄰的元素。如果第一個比第二個大,就交換他們兩個。
  2. 對第0個到第n-1個數據做同樣的工作。這時,最大的數就“浮”到了數組最后的位置上。
  3. 針對所有的元素重復以上的步驟,除了最后一個。
  4. 持續每次對越來越少的元素重復上面的步驟,直到沒有任何一對數字需要比較。

源代碼:(python實現)

1
2
3
4
5
6
7
def bubble_sort(arry):
n = len(arry) #獲得數組的長度
for i in range(n):
for j in range(1,n-i):
if arry[j-1] > arry[j] : #如果前者比后者大
arry[j-1],arry[j] = arry[j],arry[j-1] #則交換兩者
return arry

?

運行上面的代碼有錯誤,
下面是自己寫的,經過驗證:
__author__ = 'xy'

def bubble_sort(arry):
n=len(arry)
for i in range(n-1,0,-1):
flag=1
for j in range(0,i):
if arry[j] > arry[j+1]:
arry[j],arry[j+1] = arry[j+1],arry[j]
flag=0
if flag:
break
return arry

arry=[5,4,5,7,9,3,2,3,4]
print arry
bubble_sort(arry)
print arry

?

不過針對上述代碼還有兩種優化方案。

優化1:某一趟遍歷如果沒有數據交換,則說明已經排好序了,因此不用再進行迭代了。用一個標記記錄這個狀態即可。
優化2:記錄某次遍歷時最后發生數據交換的位置,這個位置之后的數據顯然已經有序,不用再排序了。因此通過記錄最后發生數據交換的位置就可以確定下次循環的范圍了。

這兩種優化方案的實現可以詳見這里。

二、選擇排序 SelectionSort

介紹:

選擇排序無疑是最簡單直觀的排序。它的工作原理如下。

步驟:

  1. 在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。
  2. 再從剩余未排序元素中繼續尋找最小(大)元素,然后放到已排序序列的末尾。
  3. 以此類推,直到所有元素均排序完畢。

源代碼:(python實現)

1
2
3
4
5
6
7
8
9
def select_sort(ary):
n = len(ary)
for i in range(0,n):
min = i #最小元素下標標記
for j in range(i+1,n):
if ary[j] < ary[min] :
min = j #找到最小值的下標
ary[min],ary[i] = ary[i],ary[min] #交換兩者
return ary

?

三、插入排序 InsertionSort

介紹:

插入排序的工作原理是,對于每個未排序數據,在已排序序列中從后向前掃描,找到相應位置并插入。

步驟:

  1. 從第一個元素開始,該元素可以認為已經被排序
  2. 取出下一個元素,在已經排序的元素序列中從后向前掃描
  3. 如果被掃描的元素(已排序)大于新元素,將該元素后移一位
  4. 重復步驟3,直到找到已排序的元素小于或者等于新元素的位置
  5. 將新元素插入到該位置后
  6. 重復步驟2~5

排序演示:

源代碼:(python實現)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def insert_sort(ary):
n = len(ary)
for i in range(1,n):
if ary[i] < ary[i-1]:
temp = ary[i]
index = i #待插入的下標
for j in range(i-1,-1,-1): #從i-1 循環到 0 (包括0)
if ary[j] > temp :
ary[j+1] = ary[j]
index = j #記錄待插入下標
else :
break
ary[index] = temp
return ary

?

四、希爾排序 ShellSort

介紹:

希爾排序,也稱遞減增量排序算法,實質是分組插入排序。由 Donald Shell 于1959年提出。希爾排序是非穩定排序算法。

希爾排序的基本思想是:將數組列在一個表中并對列分別進行插入排序,重復這過程,不過每次用更長的列(步長更長了,列數更少了)來進行。最后整個表就只有一列了。將數組轉換至表是為了更好地理解這算法,算法本身還是使用數組進行排序。

例如,假設有這樣一組數[ 13 14 94 33 82 25 59 94 65 23 45 27 73 25 39 10 ],如果我們以步長為5開始進行排序,我們可以通過將這列表放在有5列的表中來更好地描述算法,這樣他們就應該看起來是這樣:

13 14 94 33 82
25 59 94 65 23
45 27 73 25 39
10

然后我們對每列進行排序:

10 14 73 25 23
13 27 94 33 39
25 59 94 65 82
45

將上述四行數字,依序接在一起時我們得到:[ 10 14 73 25 23 13 27 94 33 39 25 59 94 65 82 45 ]。這時10已經移至正確位置了,然后再以3為步長進行排序:

10 14 73
25 23 13
27 94 33
39 25 59
94 65 82
45

排序之后變為:

10 14 13
25 23 33
27 25 59
39 65 73
45 94 82
94

最后以1步長進行排序(此時就是簡單的插入排序了)。

源代碼:(python實現)

1
2
3
4
5
6
7
8
9
10
11
12
13
def shell_sort(ary):
n = len(ary)
gap = round(n/2) #初始步長 , 用round四舍五入取整
while gap > 0 :
for i in range(gap,n): #每一列進行插入排序 , 從gap 到 n-1
temp = ary[i]
j = i
while ( j >= gap and ary[j-gap] > temp ): #插入排序
ary[j] = ary[j-gap]
j = j - gap
ary[j] = temp
gap = round(gap/2) #重新設置步長
return ary

?

上面源碼的步長的選擇是從n/2開始,每次再減半,直至為0。步長的選擇直接決定了希爾排序的復雜度。在維基百科上有對于步長串行的詳細介紹。

五、歸并排序 MergeSort

介紹:

歸并排序是采用分治法的一個非常典型的應用。歸并排序的思想就是先遞分解數組,再并數組。

先考慮合并兩個有序數組,基本思路是比較兩個數組的最前面的數,誰小就先取誰,取了后相應的指針就往后移一位。然后再比較,直至一個數組為空,最后把另一個數組的剩余部分復制過來即可。

再考慮遞歸分解,基本思路是將數組分解成leftright,如果這兩個數組內部數據是有序的,那么就可以用上面合并數組的方法將這兩個數組合并排序。如何讓這兩個數組內部是有序的?可以再二分,直至分解出的小組只含有一個元素時為止,此時認為該小組內部已有序。然后合并排序相鄰二個小組即可。

排序演示:

源代碼:(python實現)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
def merge_sort(ary):
if len(ary) <= 1 : return ary
num = int(len(ary)/2) #二分分解
left = merge_sort(ary[:num])
right = merge_sort(ary[num:])
return merge(left,right) #合并數組

def merge(left,right):
'''合并操作,
將兩個有序數組left[]和right[]合并成一個大的有序數組'''
l,r = 0,0 #left與right數組的下標指針
result = []
while l<len(left) and r<len(right) :
if left[l] < right[r]:
result.append(left[l])
l += 1
else:
result.append(right[r])
r += 1
result += left[l:]
result += right[r:]
return result

?

六、快速排序 QuickSort

介紹:
快速排序通常明顯比同為Ο(n log n)的其他算法更快,因此常被采用,而且快排采用了分治法的思想,所以在很多筆試面試中能經常看到快排的影子。可見掌握快排的重要性。

步驟:

  1. 從數列中挑出一個元素作為基準數。
  2. 分區過程,將比基準數大的放到右邊,小于或等于它的數都放到左邊。
  3. 再對左右區間遞歸執行第二步,直至各區間只有一個數。

排序演示:

源代碼:(python實現)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def quick_sort(ary):
return qsort(ary,0,len(ary)-1)

def qsort(ary,left,right):
#快排函數,ary為待排序數組,left為待排序的左邊界,right為右邊界
if left >= right : return ary
key = ary[left] #取最左邊的為基準數
lp = left #左指針
rp = right #右指針
while lp < rp :
while ary[rp] >= key and lp < rp :
rp -= 1
while ary[lp] <= key and lp < rp :
lp += 1
ary[lp],ary[rp] = ary[rp],ary[lp]
ary[left],ary[lp] = ary[lp],ary[left]
qsort(ary,left,lp-1)
qsort(ary,rp+1,right)
return ary

?

七、堆排序 HeapSort

介紹:

堆排序在 top K 問題中使用比較頻繁。堆排序是采用二叉堆的數據結構來實現的,雖然實質上還是一維數組。二叉堆是一個近似完全二叉樹 。

二叉堆具有以下性質:

  1. 父節點的鍵值總是大于或等于(小于或等于)任何一個子節點的鍵值。
  2. 每個節點的左右子樹都是一個二叉堆(都是最大堆或最小堆)。

步驟:

  1. 構造最大堆(Build_Max_Heap):若數組下標范圍為0~n,考慮到單獨一個元素是大根堆,則從下標n/2開始的元素均為大根堆。于是只要從n/2-1開始,向前依次構造大根堆,這樣就能保證,構造到某個節點時,它的左右子樹都已經是大根堆。

  2. 堆排序(HeapSort):由于堆是用數組模擬的。得到一個大根堆后,數組內部并不是有序的。因此需要將堆化數組有序化。思想是移除根節點,并做最大堆調整的遞歸運算。第一次將heap[0]heap[n-1]交換,再對heap[0...n-2]做最大堆調整。第二次將heap[0]heap[n-2]交換,再對heap[0...n-3]做最大堆調整。重復該操作直至heap[0]heap[1]交換。由于每次都是將最大的數并入到后面的有序區間,故操作完后整個數組就是有序的了。

  3. 最大堆調整(Max_Heapify):該方法是提供給上述兩個過程調用的。目的是將堆的末端子節點作調整,使得子節點永遠小于父節點 。

排序演示:

源代碼:(python實現)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
def heap_sort(ary) :
n = len(ary)
first = int(n/2-1) #最后一個非葉子節點
for start in range(first,-1,-1) : #構造大根堆
max_heapify(ary,start,n-1)
for end in range(n-1,0,-1): #堆排,將大根堆轉換成有序數組
ary[end],ary[0] = ary[0],ary[end]
max_heapify(ary,0,end-1)
return ary


#最大堆調整:將堆的末端子節點作調整,使得子節點永遠小于父節點
#start為當前需要調整最大堆的位置,end為調整邊界
def max_heapify(ary,start,end):
root = start
while True :
child = root*2 +1 #調整節點的子節點
if child > end : break
if child+1 <= end and ary[child] < ary[child+1] :
child = child+1 #取較大的子節點
if ary[root] < ary[child] : #較大的子節點成為父節點
ary[root],ary[child] = ary[child],ary[root] #交換
root = child
else :
break

?

總結

下面為七種經典排序算法指標對比情況:

轉載于:https://www.cnblogs.com/zhouwenfan-home/p/10857144.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/277733.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/277733.shtml
英文地址,請注明出處:http://en.pswp.cn/news/277733.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

誰能給我講講原理——視頻彈幕游戲!!

舍友在一個叫BliBli的視頻網站上找到這樣一個視頻彈幕游戲&#xff0c;說實話我當時一看真的驚呆了。 從來沒有見過這種能夠互動的、充滿游戲性的視頻&#xff0c;用戶WASD可以控制飛機移動躲避字幕&#xff0c;撞到字幕左上角死亡次數還可以計數&#xff0c;字幕還并不是單一…

使用BCH 操作碼的三個新型應用程序

在BCH升級之后的一個多月里&#xff0c;許多開發人員借助重新啟用的代碼進行了相關應用的開發和完善&#xff0c;比如一些類似memo和blockpress的社交軟件可以允許用戶以一種連鎖的方式提交與BCH協議綁定的數據。最近&#xff0c;有一個名為Chainfeed的應用程序&#xff0c;將所…

一段三次分拆的螞蟻搬家式MySQL遷移經歷

趁機房搬遷的機會&#xff0c;打算做一次業務整合。現有的架構是在2010年規劃并運營起來的&#xff0c;隨著時間的推移&#xff0c;項目也越來越多。打開Nginx配置文件&#xff0c;有四十多行Include包含存在&#xff0c;每一個包含就是一個項目&#xff08;有些是Web&#xff…

6.5 scp:遠程文件復制

scp命令 用于在不同的主機之間復制文件&#xff0c;它采用SSH協議來保證復制的安全性。scp命令每次都是全量完整復制&#xff0c;因此效率不高&#xff0c;適合第一次復制時使用&#xff0c;增量復制建議使用rsync命令替代。scp [option] [[user]host1&#xff1a;]file …

Adobe——我欠你一個正版

昨天&#xff0c;2014年9月24日&#xff0c;Adobe公司宣布關閉中國研發分公司。微博截圖如下。 不知道為什么自己看到這個微博&#xff0c;心里很不舒服&#xff0c;一方面是因為Adobe中國研發分公司的關閉&#xff0c;勢必會影響中國設計和研發人才的培養&#xff0c;公司解散…

“云計算的前世今生·從阿里看云計算”內蒙古師范大學劉晨旭博士專題報告會順利召開...

6月29日下午4點&#xff0c;內蒙古師范大學阿里云大數據學院邀請阿里云產品團隊專家劉晨旭博士在學術報告廳做題為《云計算的前世今生——從阿里看云計算》的專題報告分享&#xff0c;此次活動吸引了500多名師生參加&#xff0c;兩層的報告廳里座無虛席。在此次活動中&#xff…

Mac OS使用技巧之十四:自定義文件圖標

剩下的教程多是以前遺漏掉的方法&#xff0c;和一些使用的小技巧&#xff0c;做一些補充&#xff0c;希望能幫到大家。 自定義圖標對于Mac OSX用戶來說&#xff0c;Dashboard&#xff0c;Dock欄&#xff0c;壁紙以及各種鍵盤觸摸板的快捷操作都是可以高度DIY的東西。但可能許多…

1-3.監督學習(supervised learning)

定義&#xff1a;監督學習指的就是我們給學習算法一個數據集&#xff0c;這個數據集由“正確答案”組成&#xff0c;然后運用學習算法&#xff0c;算出更多的正確答案。術語叫做回歸問題 【監督學習可分為】&#xff1a;回歸問題、分類問題。兩種 例&#xff1a;一個學生從波特…

github最值得收藏的Bootstrap3后臺管理框架

github上9款最值得收藏的bootstrap3后臺管理平臺html框架 AdminLTE Gentelella Admin Vali Admin ModularAdmin Metis Ace Light Bootstrap Dashboard Material Dashboard Clearmin 1. AdminLTE AdminLTE是一個完全響應的后臺管理模板。基于Bootstrap3框架。高度可定制&#xf…

Mac OS使用技巧之十五:快捷方便的Mini Dock

Mini Dock是前面忘記了提&#xff0c;這里做一些補充。Mini Dock是Mac OSX的一個值得大書特書的亮點。雖然windows下也有類似的東西&#xff0c;但Mac下卻提供了更為全面的功能&#xff0c;通過Mini Dock欄&#xff0c;可以快速切換、隱藏、關閉正在運行的APP。這也就比之前講過…

linux下的SSHD被連接端口修改

連接別人&#xff1a;vim /etc/ssh/ssh_config 被連接&#xff1a; vim /etc/ssh/sshd_config 端口重啟生效&#xff1a; /etc/init.d/sshd restart 轉載于:https://www.cnblogs.com/gered/p/10871335.html

Mac OS使用技巧之十六:系統失去響應怎么辦?

再好的系統&#xff0c;再快的本本&#xff0c;也會在運行時因為種種原因出現卡頓或者死機等失去響應的情況。Mac用戶也會時不時碰到這種情況&#xff0c;最常見的表現為鼠標變為七彩圓圈&#xff0c;通常等上一會兒系統會自己恢復。如果遲遲沒有響應的話&#xff0c;那就需要來…

Unity Api集合

延遲重復調用方法&#xff0c; 1 方法名 2 幾秒后開始調用 3 再次重復調用的隔了多少時間InvokeRepeating(methodName:string, time:float, repeatRate:float):void; 復制代碼取消調用 CancelInvoke("SpawnerInstance"); 復制代碼利用委托來賦值一個方法進去&#xf…

單例模式--工廠模式

單例模式又稱為職責模式&#xff0c;它用來在程序中創建一個單一功能的訪問點&#xff0c;通俗地說就是實例化出來的對象是唯一的。所有的單例模式至少擁有以下三種公共元素&#xff1a;1. 它們必須擁有一個構造函數&#xff0c;并且必須被標記為private2. 它們擁有一個保存類的…

wpfのuri(讓你完全明白wpf的圖片加載方式以及URI寫法)

原文:wpfのuri&#xff08;讓你完全明白wpf的圖片加載方式以及URI寫法&#xff09;絕對 pack WPF URI pack://application:,,,/是協議&#xff1b;“&#xff0c;&#xff0c;&#xff0c;”是“///”的變體 1.資源文件 — 本地程序集 Uri uri new Uri("pack://applicati…

Mac OS使用技巧十七:豐富多彩的花哨輸入法

OSX Mavericks中的漢字輸入功能&#xff0c;絲毫不遜色于windows&#xff0c;甚至提供了強大的手寫輸入功能和語音輸入功能&#xff0c;并且發展到現在&#xff0c;已經有很多種第三方輸入法支持Mac了。 一、基本的輸入法首先說一下支持Mac的各種中文輸入法&#xff0c;其實我覺…

語言-漢語:漢語

ylbtech-語言-漢語&#xff1a;漢語漢語&#xff0c;即漢族的傳統語言&#xff0c;是中國通用語言&#xff0c;國際通用語言之一&#xff0c;屬漢藏語系&#xff0c;與藏語、壯語、侗語、黎語、彝語、苗語、瑤語等都是親屬語言。漢語歷史悠久&#xff0c;使用人數最多&#xff…

Duboo入門示例(Idea開發環境)

在學習Dubbo分布式框架時的官方入門例子&#xff0c;很有代表性。簡單清晰。 有關Dubbo的概念、概述和簡單的配置文件&#xff0c;可以看官方文檔的簡述 會很快對Duboo有個整體的概念。 準備工作: 下載示例&#xff0c;點擊這里下載&#xff0c;建議用git管理。下載注冊中心&am…

Mac OS使用技巧十八:Safari碉堡功能之一制作Widget

Safari的使用大家應該自己摸索就可以慢慢駕輕就熟&#xff0c;畢竟再高端也是個瀏覽器&#xff0c;從開始上網就要一直使用瀏覽器&#xff0c;Safari只是眾多瀏覽器中的一個比較強大的罷了。下面給大家介紹一下Safari的一個碉堡隱藏功能!!!!&#xff08;其實不算隱藏啦。。。在…

CentOS 6.5 部署WordPress

1、安裝環境: #yum install httpd mysql-server php php-mysql php-gd php-imap php-ldap php-odbc php-pear php-xml php-xmlrpc -y 2、配置mysql初始化密碼: #mysqladmin -u root password ********** 2.1、mysql新建一個wordpress的表: create database wordpress; 3、啟動服…