一步一步寫演算法(之非遞迴排序)

2021-05-28 15:15:58 字數 1707 閱讀 5843

在上面一篇部落格當中,我們發現普通查詢和排序查詢的效能差別很大。作為乙個100萬的資料,如果使用普通的查詢方法,那麼每乙個資料查詢平均下來就要幾十萬次,那麼二分法的查詢呢,20多次就可以搞定。這中間的差別是非常明顯的。既然排序有這麼好的效果,那麼這篇部落格中,我們就對排序算做乙個總結。

按照我個人的理解,排序可以分為兩種:一種是非遞迴排序,它主要按照非遞迴的方法對資料進行排序,也就是說主要資料的移位和迴圈來完成;另外一種就是遞迴方法,我們在排列當前資料的時候首先把子資料排列有序,然後才會排列當前的資料。這種不斷遞迴呼叫的方法就是遞迴排序。

非遞迴排序的方法很多,這裡主要介紹氣泡排序、插入排序、希爾排序;遞迴的方法也不少,這裡介紹的方法是快速排序、歸併排序和堆排序。排序的內容很多,本篇部落格主要介紹非遞迴排序,遞迴排序的內容主要在下一節內容解決。

(1)氣泡排序

氣泡排序的內容並不複雜。假設有n個資料需要排序,那麼我們需要確定n個從大到小的資料,每一次都挑選第n大的資料是多少,並且放大相應的位置。直到所有的資料都排列整齊了,那麼我們的排序就結束了。

void bubble_sort(int array, int length)

} }}

那麼這個程式有沒有什麼改進的地方呢?當然存在,如果發現在一次遍歷迴圈之中,如果沒有發生移位的現象,那麼是不是可以判斷這個排序可以結束了呢?朋友們可以好好思考一下這個問題?

void bubble_sort(int array, int length)

} }}

(2) 插入排序

插入排序的意思就是說,我們把資料分成兩個部分,一部分是已經排好序的資料,一部分是當前還沒有完成排序的資料。那麼這麼說來的話,排序的過程是不是就是把沒有排序的資料逐個插入到已經排好序的佇列中的過程呢。大家可以自己先試一下,然後再看看我的**對不對?

void insert_sort(int array, int length)

else

} }}

那麼插入排序有沒有像氣泡排序那樣的改進方法呢?其實沒有。因為每一次插入排序的位置都是區域性比較的結果,而氣泡排序每一次的內容都是全域性最優的。這從資料比較的次數就可以看出來。

(3)希爾排序

希爾排序,我個人認為可以看成是氣泡排序的變種。它的基本思想是:首先按照乙個序列遞減的方法逐漸進行排序。比如說有10個資料,我們按照序列5、3、1的順序進行排序。首先是5,那麼我們對1和6、2和7、3和8、4和9、5和10進行排列;第二輪是3,那麼對資料1、4、7、10排列,再對2、5、8進行排列,以及3、6、9排列;第三輪就和氣泡排序一樣了,以此對每個資料進行排列。它的優勢就是讓整個佇列基本有序,減少資料移動的次數,從而降低演算法的計算複雜度。

void shell_sort(int array, int length, int step)

for(; outer >= (index + step); outer -= step)}}

} }}

總結:

(1)上面的排序都是非遞迴程式,理解上不難,但是細節問題需要注意,特別是長度的問題

(2)**編寫的時候務必注意測試用例的設計

(3)如果可能的情況下,多使用已經驗證的**和函式

一步一步寫演算法(之非遞迴排序)

在上面一篇部落格當中,我們發現普通查詢和排序查詢的效能差別很大。作為乙個100萬的資料,如果使用普通的查詢方法,那麼每乙個資料查詢平均下來就要幾十萬次,那麼二分法的查詢呢,20多次就可以搞定。這中間的差別是非常明顯的。既然排序有這麼好的效果,那麼這篇部落格中,我們就對排序算做乙個總結。按照我個人的理...

一步一步寫演算法(之堆排序)

堆排序是另外一種常用的遞迴排序。因為堆排序有著優秀的排序效能,所以在軟體設計中也經常使用。堆排序有著屬於自己的特殊性質,和二叉平衡樹基本是一致的。打乙個比方說,處於大堆中的每乙個資料都必須滿足這樣乙個特性 1 每乙個array n 不小於array 2 n 2 每乙個array n 不小於array...

一步一步寫演算法(之快速排序)

快速排序是程式設計中經常使用到的一種排序方法。可是很多朋友對快速排序有畏難情緒,認為快速排序使用到了遞迴,是一種非常複雜的程式,其實未必如此。只要我們使用好了方法,就可以自己實現快速排序。首先,我們複習一下,快速排序的基本步驟是什麼 1 判斷輸入引數的合法性 2 把陣列的第乙個資料作為比較的原點,比...