十大排序算法

排序規則:從左至右依次增大

一、基於比較的排序算法:

插入排序:逐個遍歷未排序序列,將其在已排序序列中從右到左比較,直到遇到比自己小的數,然後將元素插入到那個數的後面,有序序列從左向右生長。

選擇排序:在未排序序列中選擇最小的元素,將其插入到已排序序列的末尾,有序序列從左向右生長。

冒泡排序:從左至右逐個比較相鄰的兩個元素,如果左邊的元素比右邊的大,則交換兩個元素位置,繼續向右比較;如果左邊的元素比右邊的元素小,則繼續比較右邊的元素和右邊的右邊的元素,直到最大的數到達序列的最右端,與上面兩種方法不同,有序序列是從右向左生長。

以上是最容易想到的三種排序算法,平均時間複雜度爲O\left ( n^{2}\right )下面是不容易想到的排序算法。

希爾排序:是改進的插入排序,首先需要將未排序序列分成幾段,比如將長度爲n的序列分爲m段,每段長度爲n/m。應該如何比較呢,是相鄰的段之間進行比較,段與段之間又是如何比較呢,是每段的同樣序號的元素進行比較,比如第i段的第2號元素和第i+1段段第2號元素進行比較,如果後者比前者小,就交換兩個元素的位置。當相鄰的段都比較完了以後,就是使得第i段元素都要比第i+1段對應位置的元素要小,得到了一個大致的排序。接着將段的長度縮短,使得比較的單位進一步縮小,這樣比較完了以後就得到了段粒度更小的有序序列,接着進一步縮小段長度,直到段長度變爲1,此時排序工作已經進行的差不多了,再進行插入排序的時候需要進行的交換工作就少了很多。這個算法像是冒泡排序和插入排序的混合版,算法的平均複雜度爲O\left ( n^{1.3}\right )

歸併排序:採用分治法的思想,將一個無序序列分爲兩段,再遞歸地一直分下去,直到分到只剩下兩個元素,然後將這兩個元素排序存好,遞歸地操作,將排好序的兩對元素合併爲有序的四個元素,將兩對四個元素合併爲有序的八個元素依次進行下去,最開始均分的兩組元素合併爲一組有序元素,這一算法的平均時間複雜度爲O\left ( n{log_{2}}^{n}\right )

快速排序:快速排序也是採用遞歸的思想,首先在無序序列中尋找一個基準,然後將元素分爲兩組,一組所有元素都比基準小,一組所有元素都比基準大,然後遞歸地對這兩組元素採用同樣的處理方式,最後就會得到一個有序的序列,這一算法的平均時間複雜度爲O\left ( n{log_{2}}^{n}\right )

堆排序:此法是利用大小堆的性質來進行排序,即父元素總是大於等於子元素,或者總是小於等於子元素。假如使用大堆結構,則每次將堆頂元素和堆底元素(底層最右側元素)交換,然後剝離堆底元素,或則序列最大值,然後將堆進行調整使其符合大堆的性質,重複上述操作,有序序列是從右向左生長的,這一算法的平均時間複雜度爲O\left ( n{log_{2}}^{n}\right )

上述算法都是基於比較多排序算法,無法突破時間複雜度O\left ( n{log_{2}}^{n}\right )的下限,下面介紹非基於比較多排序算法,它們可以達到線性的時間複雜度。

二、非基於比較的排序算法:

計數排序:此法有一定侷限性,適用於序列最大最小值相差不多並且元素爲整數的情況,它需要一個 max-min+1長度的數組作爲存儲計數空間。然後將大小爲i的元素存放在索引爲i的位置,如果沒有大小爲i的元素,則該位置的值爲0,如果有m個元素都爲i,則該元素的大小爲m。所有元素放好以後,再根據數組中元素的個數紀錄,逐個將元素回填,比如有0個元素,則不用輸出,如果有m個元素,則連續輸出m個元素,最後得到的就是有序序列。

桶排序:這個類似於哈希表,也就是電話薄原理。當每次存入一個電話的時候,電話薄會根據名字將其添加到對應的索引下,索引就是ABCDEF... 也就是名字的首字母,這相當於是一個個大桶,相同首字母的名字都被映射到一個索引下,然後桶內的名字再按照第二個字母的順序來排序,整個電話薄按照索引排序,然後所有名字就這樣有序地排列好了。

基數排序:序列中的元素可以由權重不同的關鍵字組成,比如數字由個位十位百位組成,然後分別對每一位使用計數排序。比如個位爲6的分爲一組,個位爲7的緊鄰其後。分好之後,開始按照十位數字分組,此時原先在同一組的數字可能由於十位不同而分在了不同的組,形成新的排序,然後按照放入順序依次回填,就會得到按照個位十位排序的有序序列。算法的關鍵在於迭代地使用計數排序。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章