知識點8:常見的排序算法–選擇排序

昨天我們已經介紹了快速排序的原理和實現,並且還通過幾個循環漸進的假設來腦補了一回選擇排序的執行過程。但很遺憾的是因爲這幾篇博客都沒有在我的電腦上寫的,用的是新的linux系統,也沒有java執行環境和Android開發環境。所以關於Android系列的博客會在週末更新。好了,話不多說,下面繼續我們的選擇排序算法。

選擇排序的原理

選擇排序的原理和冒泡排序比較接近,都是每次把最大或最小的值挪到數組的前面。但不同的地方在於,冒泡排序是兩個相鄰數組之間的轉換,而選擇排序則是一開始便確定了最小元素的放置位置。什麼意思呢?我們一般遍歷整個數組,找到其中的最小(或最大)元素,將其置於數組的首尾arr[0],然後從數組的第二位Arr[1]開始繼續執行遍歷,取值,交換的操作,知道整個流程結束。

選擇排序的實現

我們來看一下它的實現方式:

       void selectSort(int[] arr){ 
         int min = arr[0]; 
         int index =0; 
         for(int i=0;i<arr.length;i++){ 
             min = arr[i]; 
             index = i; 
           for(j=i+1;j<arr.length;j++){ 
            if(arr[j]<min){ 
              min =arr[j]; 
              index=j; 
            } 
          } 
          int temp = arr[i]; 
          arr[i] = arr[index]; 
          arr[index] =temp; 
       }   
      }

ps:以上代碼在c語言環境通過後手動轉化爲java代碼,但處於個人莫名的自信,這段代碼應該還是沒問題的。。。如果發現執行不了的話記得反饋啊啊啊~

另外,以上代碼的目的是爲了讓你更好地理解排序算法,但實際上,這一步是有很多冗餘代碼的,所以我們一般在理解之後,都把代碼寫成這樣:

 void selectSort(int[] arr){  
         int min_index =0; 
         for(int i=0;i<arr.length;i++){  
             min_index = i; 
           for(j=i+1;j<arr.length;j++){ 
            if(arr[j]<arr[min_index]){ 
              arr[min_index]=arr[j]; 
              index=j; 
            } 
          } 
          int temp = arr[i]; 
          arr[i] = arr[min_index]; 
          arr[min_index] =temp; 
       }   
      }

如此,便實現了簡單的選擇排序。那麼,還有沒有更好的優化方式呢?有的,那就是雙向選擇排序:

雙向選擇排序

何爲雙向選擇排序呢?我們假設要使數組從小到大進行排序,那麼如果用簡單的選擇排序,則是每次得到最小值,然後再將其至於數組首位是吧。可是我們能不能一次性取最大值和最小值,分別置於數組的末位和首位,以此減少數組的循環次數呢?答案是可以的,這就是雙向選擇排序的思路。但是,雙向選擇排序不像簡單排序那樣,它對數組元素的關聯性要求很高,也就是說當我們需要進行元素置位時,需要考慮多種情況,邏輯上顯得複雜,難以理解。因此,在這裏僅當參考,就不再寫成java的格式了。


代碼更新:昨晚測試雙向選擇時發現有的地方存在bug,目前已經重新調整,如果有用例測試不通過的,麻煩反饋一下哈!~

void selectSort(int arr[],int num){
    int minindex =0;
    int maxindex = 0;
    int i,j;
    int size=num;
    int temp;
    for(j=0;j<size;j++){
            minindex = j;
            maxindex = j;
        for(i=j;i<=size-1;i++){
            if(arr[i]<=arr[minindex]){
                minindex=i;
                continue;
            }
            if(arr[i]>=arr[maxindex]){
                maxindex = i;
            }
        }

        if(minindex != maxindex){
            if( maxindex==j && maxindex+minindex == num-1){
                temp = arr[minindex];
                arr[minindex]=arr[maxindex];
                arr[maxindex]=temp;
            }else if(minindex - maxindex ==1 && maxindex==j &&minindex==size){
                temp = arr[minindex];
                arr[minindex]=arr[maxindex];
                arr[maxindex]=temp;
            }else if(maxindex==j){
                temp = arr[maxindex];
                arr[maxindex] = arr[size-1];
                arr[size-1] = temp;
                temp = arr[minindex];
                arr[minindex] = arr[j];
                arr[j] = temp;
            }else if(minindex==size){
                temp = arr[minindex];
                arr[minindex] = arr[j];
                arr[j] = temp;
                temp = arr[maxindex];
                arr[maxindex] = arr[size];
                arr[size] = temp;
            }else{
                temp = arr[minindex];
                arr[minindex] = arr[j];
                arr[j] = temp;
                temp = arr[maxindex];
                arr[maxindex] = arr[size-1];
                arr[size-1] = temp;
            }
        }
        size--;     
}

以上就是雙向選擇排序的算法實現,當然還有優化的地方,比如將元素交換封裝成方法,添加其他的邊界檢測條件等。此處不一一贅述,只是把實現思路釐清。
以便有更好的理解。

下一章:知識點9:常見的排序算法–插入排序,敬請期待~

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