数据结构与算法:排序算法的稳定性以及各性能比较python实现
招聘筆試中經(jīng)常會考到排序算法,在此做一個總結(jié)。
一、算法概念
1.排序算法的穩(wěn)定性
假定在待排序的記錄序列中,存在多個具有相同的關(guān)鍵字的記錄,若經(jīng)過排序,這些記錄的相對次序保持不變,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,則稱這種排序算法是穩(wěn)定的;否則稱為不穩(wěn)定的。
1.簡單選擇排序
一趟簡單排序的操作為:通過n-i次關(guān)鍵字間的比較,從n-i+1個記錄中選出關(guān)鍵字最小的記錄,并和第i(1<=i<=n)個記錄交換之。
- 時間復雜度:
- 空間復雜度:
- 穩(wěn)定性:不穩(wěn)定
2.冒泡排序
它重復地走訪過要排序的元素列,依次比較兩個相鄰的元素,如果他們的順序(如從大到小、首字母從A到Z)錯誤就把他們交換過來。走訪元素的工作是重復地進行直到?jīng)]有相鄰元素需要交換,也就是說該元素已經(jīng)排序完成。
- 時間復雜度:
- 空間復雜度:
- 穩(wěn)定性:穩(wěn)定
3.插入排序?
將序列的第一個元素當做已經(jīng)排序好的序列,然后從后面的第二個元素開始,逐個元素進行插入,直到整個序列有序為止。第i趟操作為:在含有i-1個記錄的有序子序列r[1...i-1]中插入一個記錄r[i]后,變成含有i個記錄的有序子序列r[1..i]。
- 時間復雜度:
- 空間復雜度:
- 穩(wěn)定性:穩(wěn)定
4.希爾排序
希爾排序(有時稱為“遞減遞增排序”縮小增量排序 Diminishing Increment Sort)通過將原始列表分解為多個較小的子列表來改進插入排序,每個子列表使用插入排序進行排序。 選擇這些子列表的方式是希爾排序的關(guān)鍵。不是將列表拆分為連續(xù)項的子列表,希爾排序使用增量i(有時稱為?gap),通過選擇 i 個項的所有項來創(chuàng)建子列表。
下圖1中顯示增量為3得到的子列表。個子列表可以通過插入排序進行排序。完成這些排序后,我們得到如圖2所示的列表。雖然這個列表沒有完全排序,但發(fā)生了很有趣的事情。 通過排序子列表,我們已將項目移動到更接近他們實際所屬的位置。
圖1-2?
圖3展示了使用增量為 1 的插入排序; 換句話說,標準插入排序。注意,通過執(zhí)行之前的子列表排序,我們減少了將列表置于其最終順序所需的移位操作的總數(shù)。對于這種情況,我們只需要四次移位完成該過程。
圖3?
- 時間復雜度:?當n在某個特定范圍內(nèi),希爾排序所需的比較和移動次數(shù)約為,當時,可以減少到
- 空間復雜度:
- 穩(wěn)定性:不穩(wěn)定
5.堆排序
詳細原理介紹請看相關(guān)博文:
https://blog.csdn.net/qq_18888869/article/details/88886270
6.歸并排序
首先介紹一下分治法(Divide and Conquer)
很多有用的算法結(jié)構(gòu)上是遞歸的,為了解決一個特定問題,算法一次或多次遞歸調(diào)用其自身以解決若干子問題。這些算法遵循分值的思想。分治法在每層遞歸時有三個步驟:
- 分解:分解原問題為若干子問題,這些子問題是原問題的規(guī)模最小的實例
- 解決:解決這些子問題,遞歸的求解這些子問題。當子問題規(guī)模足夠小,就可以直接求解
- 合并:合并這些子問題的解成原問題的解
下面介紹歸并排序如何利用分治法解決問題:
考慮我們排序這個數(shù)組:[10,23,51,18,4,31,13,5] ,我們遞歸地將數(shù)組進行分解?
?當數(shù)組被完全分隔成只有單個元素的數(shù)組時,我們需要把它們合并回去,每次兩兩合并成一個有序的序列。
?
python實現(xiàn):?
- 分解:將待排序的n個元素分成各包含n/2個元素的子序列
- 解決:使用歸并排序遞歸排序兩個子序列
- 合并:合并兩個已經(jīng)排序的子序列以產(chǎn)生已排序的答案
- 時間復雜度:?
- 空間復雜度:
- 穩(wěn)定性:穩(wěn)定
7.快速排序
快排(與歸并排序一樣)也是一種分而治之(divide and conquer)的策略。歸并排序把數(shù)組遞歸成只有單個元素的數(shù)組,之后再不斷兩兩 合并,最后得到一個有序數(shù)組。這里的遞歸基本條件就是只包含一個元素的數(shù)組,當數(shù)組只包含一個元素的時候,我們可以認為它本來就是有序的(當然空數(shù)組也不用排序)。
快排的工作過程其實比較簡單,三步走:
-
選擇基準值 pivot 將數(shù)組分成兩個子數(shù)組:小于基準值的元素和大于基準值的元素。這個過程稱之為 partition
-
對這兩個子數(shù)組進行快速排序。
-
合并結(jié)果
- 時間復雜度:?
- 空間復雜度:
- 穩(wěn)定性:不穩(wěn)定
?
#快速排序 def quick_sort(list2, low, high):print('quick_sort:') # list2 = list1.copy()if len(list2[low:high+1]) <= 1:return list2else:list2, pivot = partition(list2, low, high)print(list2)quick_sort(list2, low, pivot-1 )quick_sort(list2, pivot+1, high)print(list2)def partition(list2, low, high): # list2 = list1.copy()pivotkey = list2[low] while low < high: # print('low, high: {},{}'.format(low, high))while low < high and pivotkey < list2[high]:high -= 1 # print('high:',high)list2[low] = list2[high]while low < high and pivotkey > list2[low]:low += 1 # print('low:', low)list2[high] = list2[low]list2[low] = pivotkeyreturn list2, low8.基數(shù)排序
| 排序方法 | 平均時間復雜度 | 最好時間復雜度 | 最壞時間復雜度 | 輔助空間 | 穩(wěn)定性 | 備注 |
| 冒泡排序 | O(n2) | O(n) | O(n2) | O(1) | 穩(wěn)定 | n小時較好 |
| 簡單選擇排序 | O(n2) | O(n2) | O(n2) | O(1) | 不穩(wěn)定 | n小時較好 |
| 直接插入排序 | O(n2) | O(n) | O(n2) | O(1) | 穩(wěn)定 | 大部分已排序時較好 |
| 希爾排序 | O(nlogn)~O(n2) | O(n1.3) | O(n2) | O(1) | 不穩(wěn)定 | s是所選分組 |
| 堆排序 | O(nlogn) | O(nlogn) | O(nlogn) | O(1) | 不穩(wěn)定 | n大時較好 |
| 歸并排序 | O(nlogn) | O(nlogn) | O(nlogn) | O(n) | 穩(wěn)定 | n大時較好 |
| 快速排序 | O(nlogn) | O(n) | O(n2) | O(nlogn)~O(n) | 不穩(wěn)定 | n大時較好 |
github代碼:https://github.com/makang101/python-data-structure?
參考:
problem-solving-with-algorithms-and-data-structure-using-python 中文版
數(shù)據(jù)結(jié)構(gòu)(C語言版)嚴蔚敏
總結(jié)
以上是生活随笔為你收集整理的数据结构与算法:排序算法的稳定性以及各性能比较python实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python:copy()和deepco
- 下一篇: 数据结构与算法:树与二叉树python实