排序演算法的比較 選擇及其改進

2022-08-13 17:21:10 字數 3336 閱讀 4675

一、引言

排序是電腦科學中最重要的研究問題之一, 它在計算機圖形、計算機輔助設計、機械人、模式識別及統計學等領域具有廣泛的應用。由於它固有的理論上的重要性,2023年它被列為對科學和工程計算的研究與實踐影響最大的10大問題之一。其功能是將乙個資料元素的任意序列重新排列成乙個按關鍵字有序的序列。

二、排序演算法的效能比較

內部排序演算法種類繁多,但就其排序時所遵循的原則而言,大致可分為五大類:插入排序、交換排序、選擇排序、歸併排序和基數排序。演算法效能的比較主要是從時間複雜度、空間複雜度和穩定性三個方面來綜合考慮。

(一)時間複雜度

從平均效能上看,直接插入排序、簡單選擇排序、氣泡排序這三種「簡單排序」為第一類,其時間複雜度均為o(n2);堆排序、歸併排序、快速排序屬於第二類,其時間複雜度均為o(nlog2n);基數排序則屬於第三類,其時間複雜度為 o(d(n+rd)),也可以寫為o(dn),因此最適用於n值很大而關鍵字較小的序列。

當原表有序或基本有序時,直接插入排序和氣泡排序將大大減少比較次數和移動記錄的次數,時間複雜度可降至o(n);而快速排序則相反,當原表基本有序時,將蛻化為氣泡排序,時間複雜度提高為o(n2);原表是否有序,對簡單選擇排序、堆排序、歸併排序和基數排序的時間複雜度影響不大。

(二)空間複雜度

從空間複雜度來看,歸併排序最大,對 n 個記錄需要附加等量的儲存量,其空間複雜度為o(n);基數排序次之,它需要附加較多儲存空間用於儲存佇列指標和用作結點指標域,空間複雜度為o(rd);快速排序單獨討論,其遞迴演算法需要使用堆疊來實現,棧中存放待排序記錄序列的首尾位置,在一般情況下需要棧空間o(nlog2n),最壞情況下,所需要的棧空間為o(n);其餘排序演算法的空間複雜度最小,僅為o(1)。

(三)穩定性

從演算法的穩定性而言,所有排序演算法可分為兩類:直接插入排序、簡單選擇排序、氣泡排序、歸併排序和基數排序為第一類,均屬於穩定的演算法,而快速排序和堆排序則屬於第二類,是不穩定演算法。

三、排序演算法的選擇

根據以上的效能比較,我們發現每種排序演算法都各有優缺點。因此,在實用時需根據不同情況適當選用,甚至可以將多種方法結合起來使用。

(一)選擇排序演算法的依據

影響排序的因素有很多,平均時間複雜度低的演算法並不一定就是最優的。相反,有時平均時間複雜度高的演算法可能更適合某些特殊情況。同時,選擇演算法時還得考慮它的可讀性,以利於軟體的維護。一般而言,需要考慮的因素有以下四點:

1.待排序的記錄數目n的大小;

2.記錄本身資料量的大小,也就是記錄中除關鍵字外的其他資訊量的大小;

3.關鍵字的結構及其分布情況;

4.對排序穩定性的要求。

(二)選擇排序演算法的結論

依據上述在選擇排序演算法時需考慮的因素,可以得出以下幾個結論:

1.資料量不大時選用插入或選擇排序,一般不使用或不直接使用傳統的氣泡排序;

2.當資料量大而又注重空間複雜性時選擇快速排序或堆排序等;

3.在已排序資料上增加若干新資料時,建議使用插入排序;

4.當資料量大而又允許使用較多附加空間時可選擇桶排序。

四、一些排序演算法的改進策略

常用的排序演算法中,有不少是可以根據實際情況而進一步改進完善的,以充分提高演算法的效率。

(一)簡單選擇排序的改進二元選擇排序

傳統的簡單選擇排序,每趟迴圈只能確定乙個元素排序後的定位。我們可以考慮改進為每趟迴圈確定兩個元素(當前趟最大和最小記錄)的位置,從而減少排序所需的迴圈次數。改進後對n個資料進行排序,最多隻需進行[n/2]趟迴圈即可。具體實現如下:

void selectsort(rectype r[ ],int n)

if (r[j].key < r[min ].key)

}/* end of for j */

r[0]=r[i-1];r[i-1]=r[min];r[min]=r[0];

r[0]=r[n-i];r[n-i]=r[max];r[max]=r[0];

/*該交換操作還可分情況討論以提高效率*/

} /* end of for i*/

} /* end of selectsort */

(二)氣泡排序演算法的改進

對氣泡排序常見的改進方法是加入一標誌性變數exchange,用於標誌某一趟排序過程中是否有資料交換,如果進行某一趟排序時並沒有進行資料交換,則說明資料已經按要求排列好,可立即結束排序,避免不必要的比較過程。本文再提供以下兩種改進演算法:

1.設定一標誌性變數pos, 用於記錄每趟排序中最後一次進行交換的位置。由於pos位置之後的記錄均已交換到位, 故在進行下一趟排序時只要掃瞄到pos位置即可。

改進後演算法如下:

void bubble_1 ( rectype r[ ], int n) /* end of if */

i= pos; /*為下一趟排序作準備*/

} /* end of while */

}/* end of bubble_1 */

2.傳統氣泡排序中每一趟排序操作只能找乙個最大值或最小值,我們考慮利用在每趟排序中進行正向和反向兩遍冒泡的方法一次可得到兩個最終值(最大者和最小者) , 從而使排序趟數幾乎減少了一半。

改進後的演算法實現為:

void bubble_2 ( rectype r[ ], int n)

high - -; /*修改high值, 前移一位*/

for ( j=high; j>low; j- - )

/*反向冒泡, 找到最小者*/

if (r[j].keyr[0]= r[j]; r[j]= r[j-1];

r[j-1]= r[0];}

low + +; /*修改low值, 後移一位*/

} /* end of while */

} /* end of bubble_2 */

3.快速排序的改進。在本改進演算法中,只對長度大於k的子串行遞迴呼叫快速排序,讓原序列基本有序,然後再對整個基本有序序列用插入排序演算法排序。實踐證明,改進後的演算法時間複雜度有所降低,且當k取值為 8 左右時,改進演算法的效能最佳。演算法思想如下:

void quicksort(rectype r[ ])

r[j+1]=r[0];

} /* end of for */

} /* end of quicksort */

qsort(rectype r[ ],int low,int high) /* end of if */

} /* end of qsort */

五、結束語

排序演算法應用廣泛,是程式設計中的一種重要操作,充分了解各演算法的效能優劣和選擇的基本原則,在實際應用中具有重要的意義。針對常用的幾種排序演算法,本文提出了一些相應的改進策略及其詳細的c語言實現,實踐證明,這些改進演算法具有較好的執行效果。

本文**:全刊雜賞析網

選擇排序及其改進 堆排序

include include iomanip using namespace std 選擇排序思想 每一趟 如第i趟 從後面n i 1個待排序的元素中選出關鍵字最小的元素,作為有序子串行 前i 1個有序 的第i個元素,直至n 1趟結束。因為最後乙個元素是不用再排序的 沒有比它再小的元素了,他是最後...

氣泡排序及其改進演算法

第乙個排序函式 sort1 為氣泡排序的典型實現,第二和第三個為改進後的排序函式 include include define len 20000 double sort1 int int double sort2 int int double sort3 int int int main int ...

選擇排序演算法改進隨筆

選擇排序演算法改進隨筆 這是一道選擇排序改進的小測試,想法,在一次遍歷中直接選取出最大值和最小值,然後分別移動到頭尾,主要難點在於邊界的處理,因為使用了兩次swap,第一次使用swap會造成index變化,第二次使用swap的時候就需要注意。主要是兩種情況 當最大值出現在頭,或者最大值出現在頭,最小...