上次說冒泡排序留下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交換元素),還有就是內存開銷
本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。