天天看點

非遞歸排序

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

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

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

(1)冒泡排序

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

view plaincopy to clipboardprint?

  1. void bubble_sort(int array[], int length)
  2. {
  3. int inner = 0, outer = 0;
  4. int median = 0;
  5. if(NULL == array || 0 == length)
  6. return;
  7. for(outer = length-1; outer >= 1; outer --){
  8. for(inner = 0; inner < outer; inner ++){
  9. if(array[inner] > array[inner + 1]){
  10. median = array[inner];
  11. array[inner] = array[inner + 1];
  12. array[inner + 1] = median;
  13. }

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

  1. int flag = 1;
  2. for(outer = length-1; outer >= 1 && flag; outer --){
  3. flag = 0;
  4. if(flag == 0)
  5. flag = 1;

(2) 插入排序

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

  1. void insert_sort(int array[], int length)
  2. int inner = 0;
  3. int outer = 0;
  4. for(outer = 1; outer <length; outer ++){
  5. for(inner = outer; inner >= 1; inner --){
  6. if(array[inner] < array[inner -1]){
  7. array[inner] = array[inner -1];
  8. array[inner -1] = median;

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

(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排列;第三輪就和冒泡排序一樣了,以此對每個資料進行排列。它的優勢就是讓整個隊列基本有序,減少資料移動的次數,進而降低算法的計算複雜度。

  1. void shell_sort(int array[], int length, int step)
  2. for(; step >= 1; step -=2){
  3. for(int index = 0; index < step; index ++){
  4. if((length -1) < (index + step))
  5. continue;
  6. else{
  7. outer = index + step;
  8. while( (outer + step) <= (length - 1))
  9. outer += step;
  10. for(; outer >= (index + step); outer -= step){
  11. for(inner = index; inner <= outer - step; inner += step){
  12. if(array[inner] >= array[inner + step]){
  13. array[inner] = array[inner + step];
  14. array[inner + step] = median;

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

總結:

繼續閱讀