数据结构:排序趟数 / 比较次数与序列的原始状态有关的排序方法有哪些?
先說結論
比較次數 與序列初態 無關 的算法是:二路歸并排序、簡單選擇排序、基數排序
比較次數 與序列初態 有關 的算法是:快速排序、直接插入排序、冒泡排序、堆排序、希爾排序
排序趟數 與序列初態 無關 的算法是:直接插入排序、折半插入排序、希爾排序、簡單選擇排序、歸并排序、基數排序
排序趟數 與序列初態 有關 的算法是:冒泡排序、快速排序
關于排序趟數
插入排序、選擇排序 趟數都是固定的 n-1。對于插入排序來說,即使序列有序,也要依次從第二個元素開始,向前找它的插入位置。
冒泡排序 趟數與數據有關,優化冒泡排序的最優復雜度為O(n),其主要優化就是記錄了前一趟是否冒泡,如果沒有產生冒泡就說明數組已經有序,直接return。如果產生了冒泡,才繼續執行。
快速排序 的排序趟數就是它的遞歸深度。當 快排 的數據是有序時候,會退化為冒泡,所以快排趟數也與初始序列順序有關了。如下圖:
關于比較次數
有同學在評論中提出了疑問,我在這里補充一下吧,關于對于比較次數和初始狀態的關系的理解
堆排序:比如元素下沉的操作,雖然一個元素是從底部拉上來的,但這不代表這個元素一定會接著沉到底部,如果沉到中間就停止下沉的話,比較次數就少了。而這個過程的比較次數自然和下沉的深度是相關的。
希爾排序:希爾排序是對簡單插入排序的改進,每一趟希爾的內部使用的就是簡單插入排序。而簡單插入排序隨著數據變成正序時,執行效率最好,每次插入都不用移動前面的元素,時間復雜度為O(N)。當數據是反序時,執行效率最差,此時時間復雜度為O(N*N). 類比到希爾排序中,希爾排序本身就是屬于插入排序。當然會隨著有序而少比較幾次。
(這里說的比較次數是精確的次數,區別于時間復雜度的概念,時間復雜度只是描述了數量級)
選擇排序
i 從頭開始,每次遍歷之后所有的元素,k 從 i 開始,向后標記 選出 最小的元素,循環后如果大于 i ,則與 i 位置元素 交換,一直到最后。
簡單選擇排序它最大的特點是,交換移動數據次數相當少,這樣也就節約了相應的時間,無論最好最壞的情況,其比較次數都是一樣多。第 i 次排序需要進行n-i 次關鍵字的比較,此時需要比較n-1+n-2+…+1=n(n-1)/2次,所以 總比較次數 與初始狀態 無關,時間復雜度為O(n^2)。
對于交換次數而言,最差的時候,也就初始排序,交換次數為n-1次,復雜度為O(n)。當全部已經排序好時,則不發生交換,所以 元素總移動次數 與初始狀態 有關。
直接插入排序
從當前關鍵字之前的關鍵字開始掃描,如果大于待排關鍵字,則后移一位。直到全部記錄插入完成。
如果全部有序,則只需要遍歷一趟就完成了排序,比較次數為 n-1,并且在這個過程中沒有發生元素的移動。因此,比較次數 與序列初態 有關 。初始序列基本有序時,移動元素最少(效率最高)。
void insertSort(int A[],int n) {int i, j, temp;for (i = 1; i < n; i++) { // 將各元素插入已經排好的序列中if (A[i] < A[i - 1]) { // 若A[i]關鍵字小于前驅temp = A[i]; // 用 temp 暫存 A[i]for (j = i - 1; j >= 0 && A[j] > temp; --j) // 檢查所有前面已經排好序的元素A[j + 1] = A[j]; // 將所有大于 temp 的元素右移一個位置A[j + 1] = temp; // 復制到插入位置}} }若使用 折半插入 來進行優化,雖然減少了元素的比較次數,但并未使時間復雜度脫離O(n^2)
關于算法復雜度與序列初態的關系
算法復雜度 與初始狀態 無關 的有哪些?
首先看內排序總結表:
由表中紅線標出的地方可以輕易得出,以下四種排序方法的算法復雜度與數組的初始狀態無關:
一堆(堆排序)烏龜(歸并排序)選(選擇排序)基(基數排序)友。
總結
以上是生活随笔為你收集整理的数据结构:排序趟数 / 比较次数与序列的原始状态有关的排序方法有哪些?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数据结构:堆和败者树的区别是什么?
- 下一篇: 数据结构:试设计一个算法,改造一个带表头