首页 > 代码库 > 排序算法-冒泡排序(改),选择排序
排序算法-冒泡排序(改),选择排序
上次说冒泡排序留下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交换元素),还有就是内存开销
排序算法-冒泡排序(改),选择排序