1. 程式人生 > >排序演算法(二)——選擇排序及改進

排序演算法(二)——選擇排序及改進

選擇排序

基本思想

氣泡排序中有一個缺點,比如,我們比較第一個數a1與第二個數a2的時候,只要a1比a2大就會交換位置,但是我們並不能確定a2是最小的元素,假如後面還有比它更小的,該元素還會與a2再次進行交換,而且這種交換有可能發生多次才能確定a2的最終位置。

選擇排序可以避免這種耗費時間的交換操作,從第一個元素開始,掃描整個待排陣列,找到最小的元素放之後再與第一個元素交換位置,然後再從第二個元素開始,繼續尋找最小的元素與第二個元素交換位置,依次類推。


java實現

//選擇排序
   public void selectionSort(){
       int minPoint;  //儲存最小元素的小標
       int len = array.length;
       int temp;
       int counter = 1;
      
       for(int i=0;i<len-1;i++){
         
          minPoint= i; 
          for(int j=i+1;j<=len-1;j++){  //每完成一輪排序,就確定了一個相對最小元素,下一輪排序只對後面的元素排序
              if(array[j]<array[minPoint]){  //如果待排陣列中的某個元素比當前元素小,minPoint指向該元素的下標
                 minPoint= j;
              }
          }
         
          if(minPoint!=i){  //如果發現了更小的元素,交換位置
              temp= array[i];
              array[i]= array[minPoint];
              array[minPoint]= temp;
          }
         
          System.out.print("第"+counter+"輪排序結果:");
          display();
          counter++;
       }
   }


演算法分析

選擇排序與氣泡排序一樣,需要進行N*(N-1)/2次比較,但是隻需要N次交換,當N很大時,交換次數的時間影響力更大,所以選擇排序的時間複雜度為O(N2)

雖然選擇排序與氣泡排序在時間複雜度屬於同一量級,但是毫無疑問選擇排序的效率更高,因為它的交換操作次數更少,而且在交換操作比比較操作的時間級大得多時,選擇排序的速度是相當快的。

選擇排序的改進

傳統的選擇排序每次只確定最小值,根據改進冒泡演算法的經驗,我們可以對排序演算法進行如下改進:每趟排序確定兩個最值——最大值與最小值,這樣就可以將排序趟數縮減一半。

改進後的程式碼如下:

//選擇排序改進版
   public void selectionSort_improvement(){
       int minPoint;  //儲存最小元素的小標
       int maxPoint;  //儲存最大元素的小標
       int len = array.length;
       int temp;
       int counter = 1;
      
       for(int i=0;i<len/2;i++){
         
          minPoint= i;
          maxPoint= i;
          for(int j=i+1;j<=len-1-i;j++){  //每完成一輪排序,就確定了兩個最值,下一輪排序時比較範圍減少兩個元素
              if(array[j]<array[minPoint]){  //如果待排陣列中的某個元素比當前元素小,minPoint指向該元素的下標
                 minPoint= j;
                 continue;
              }else if(array[j]>array[maxPoint]){  //如果待排陣列中的某個元素比當前元素大,maxPoint指向該元素的下標
                 maxPoint= j;
              }
          }
         
          if(minPoint!=i){  //如果發現了更小的元素,與第一個元素交換位置
              temp= array[i];
              array[i]= array[minPoint];
              array[minPoint]= temp;
             
              //原來的第一個元素已經與下標為minPoint的元素交換了位置
              //如果之前maxPoint指向的是第一個元素,那麼需要將maxPoint重新指向array[minPoint]
              //因為現在array[minPoint]存放的才是之前第一個元素中的資料
              if(maxPoint== i){
                 maxPoint= minPoint;
              }
             
          }
 
          if(maxPoint!=len-1-i){  //如果發現了更大的元素,與最後一個元素交換位置
              temp= array[len-1-i];
              array[len-1-i]= array[maxPoint];
              array[maxPoint]= temp;
          }
         
          System.out.print("第"+counter+"輪排序結果:");
          display();
          counter++;
       }
   }