首页 > 代码库 > 排序算法-冒泡排序(改),选择排序

排序算法-冒泡排序(改),选择排序

上次说冒泡排序留下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交换元素),还有就是内存开销

 

排序算法-冒泡排序(改),选择排序