排序演算法(二)——選擇排序及改進
阿新 • • 發佈:2019-01-29
選擇排序
基本思想
氣泡排序中有一個缺點,比如,我們比較第一個數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++; } }