排序算法-冒泡排序(改),選擇排序


上次說冒泡排序留下2個問題,一個是選擇排序,一個是冒泡排序性能,這次會先說選擇排序,然后說冒泡排序的優化

一選擇排序

選擇排序是一種簡單直觀的排序算法。它的工作原理是每一次從待排序的元素中選出最小(或最大)的一個元素,存放在序列的起始位置,直到全部待排序的數據元素排完

流程:

  (有小到大排序)

  第一輪

  將0位元素與后續所有元素比較,將小的元素放在0位

  第二輪

  將1位元素與后續所有元素比較,將小的元素放在1位

  ...

  直到最后一位

 

代碼上次已經貼出,這里復制下

 1   public static void SelectSort1(int[] array)
 2         {
 3             for (int i = 0; i < array.Length - 1; i++)
 4             {
 5                 //注意這里內循環處理不同
 6                 for (int j = i + 1; j < array.Length; j++)
 7                 {
 8                     int c = array[i];
 9                     //這里是i位與j位比較
10                     if (array[i] > array[j])
11                     {
12                         array[i] = array[j];
13                         array[j] = c;
14                     }
15                 }
16             }
17         }

 

到目前說了2種很簡單的排序,可以看出排序主要涉及操作包括,1遍歷選出每個元素 2與其他元素比較 3交換元素位子 排序肯定會 1遍歷選出每個元素 ,    所以排序算法的效率問題主要是看 2 ,3操作的次數,所以我們在優化算法時 主要考慮,2,3操作 ,還有就是算法會用一些變量來保存中間數據等,還會涉及額外內存使用,

二 接下來說說冒泡排序的優化問題

1 數據本來就是有序的,或者本來趨近有序,只需要幾次就能完成,但是前面說的冒泡排序總會進行完整的比較

比如數組a: 9,1,2,3,4,5

  數組b: 1,2,3,5,4

這種情況就是在前幾次就已近排序完成,后面會進行無意義的比較

優化方法:添加一個標記,當某一趟比較沒有出現元素交換位子,說明排序已近完成,可以直接退出(主要是減少外循環)

代碼:

 1  public static void BubbleSort2(int[] array)
 2         {
 3             for (int i = 0; i < array.Length - 1; i++)
 4             {
 5                 //默認沒有發生交換
 6                 bool change = false;
 7                 for (int j = 0; j < array.Length - 1 - i; j++)
 8                 {
 9                     if (array[j] > array[j + 1])
10                     {
11                         int c = array[j];
12                         array[j] = array[j + 1];
13                         array[j + 1] = c;
14 
15                         //發生交換
16                         change = true;
17                     }
18                 }
19                 //未發生交換,退出循環
20                 if (!change)
21                 {
22                     break;
23                 }
24             }
25         }

 

 

2上面是減少了外循環,其實還可以減少內循環

比如數組 3,2,1,4,5,6,7,8,9,10

這種情況,在第一趟循環時可以判斷到內循環中4到后面元素都是有序的,所以可以標記這個位子,下一趟循環時就不用再 遍歷后面的元素了

代碼

 

 1  public static void BubbleSort3(int[] array)
 2         {
 3             //本次循環最后一個交換位子的元素,這個元素后面則為有序元素
 4             int lastChange = array.Length - 1;
 5             //上次交換位子的元素,本次內循環需要遍歷到元素為止
 6             int change;
 7             for (int i = 0; i < array.Length - 1; i++)
 8             {
 9                 change = lastChange;
10                 for (int j = 0; j < change; j++)
11                 {
12                     if (array[j] > array[j + 1])
13                     {
14                         int c = array[j];
15                         array[j] = array[j + 1];
16                         array[j + 1] = c;
17 
18                         //本次循環交換位子
19                         lastChange = j;
20                     }
21                 }
22 
23                 //本次未發生交換位子,說明已近有序了
24                 if (lastChange == change)
25                 {
26                     break;
27                 }
28             }
29         }

 

三 現在可以看出上面選擇排序其實還是有點問題

比如:數組:9,8,7,6,5,4,3,2,1

有小到大排序的話,按照上面的選擇排序,0位元素會不斷與后面元素交換位子,直到與最后一位交換,按照有小到大排序,9直接與1交換就好了,要知道元素交換是很消耗性能的

解決方案:添加一個標記,每次比較時保存較小(較大)的元素下表,最后才根據標記進行交換位子

代碼:

 1 public static void SelectSort2(int[] array)
 2         {
 3             for (int i = 0; i < array.Length - 1; i++)
 4             {
 5                 //標記最小值下表
 6                 int minValueIndex = i;
 7                 for (int j = i + 1; j < array.Length; j++)
 8                 {
 9                     //這里是最小值與j位比較
10                     if (array[minValueIndex] > array[j])
11                     {
12                         minValueIndex = j;
13                     }
14                 }
15                 //如果當前位置不是最小值,則交換
16                 if (minValueIndex != i)
17                 {
18                     int c = array[i];
19                     array[i] = array[minValueIndex];
20                     array[minValueIndex] = c;
21                 }
22             }
23         }

 

總結下:

排序算法主要要注意的3個操作(1遍歷選出所有元素,2與其他元素比較3交換元素),還有就是內存開銷

 


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com