排序算法系类-交换之冒泡优化

来源:互联网 发布:工业革命 知乎 编辑:程序博客网 时间:2024/06/06 19:12

前言

上一篇博客介绍了冒泡排序:点击打开链接,今天我来说说冒泡的优化。


优化一

冒泡排序的重要思想就是两两比较,然后交换,这样对于一组杂乱无章的小型数组来说是很有效的,但是如果一个数组经过几轮交换已经变的有序了,例如[2,1,3,4,5,6,7]这个数组,经过第一轮,已经变成有序的了,但顽固的冒泡还是要继续进行没有营养的两两比较,从而牺牲了时间。所以对于这种情况,对冒泡排序进行小型整容,便可以减少程序运行时间。

原理

方法就是用一个flag来判断一下,当前数组是否已经有序,如何判断是否有序呢?如果里面一层循环在某次扫描中没有执行交换,则说明此时数组已经全部有序列,无需再扫描了。因此,每次发生交换,就标记,如果某次循环完没有标记,则说明已经完成排序,退出循环,这样可以明显的提高冒泡排序的表现~

代码如下

    void maopao2(int a[], int size)      {          bool flag = true;          for (int i = 0; i < size -1; i++)          {              // 每次先重置为false              flag = false;              for (int j = size - 1; j > i ; j--)              {                  if (a[j-1] > a[j])                  {                      int temp = a[j-1];                      a[j-1] = a[j];                      a[j] = temp;                            flag = true;                  }              }              // 如果上一次扫描没有发生交换,则说明数组已经全部有序,退出循环              if (!flag)                  break;          }      }  

优化二

原理

在第一步优化的基础上发进一步思考:如果R[i..n]已是有序区间,上次的扫描区间是R[0..i],记上次扫描时最后 一次执行交换的位置为lastSwapPos,则lastSwapPos在o与i之间,不难发现R[lastSwapPos..i]区间也是有序的,否则这个区间也会发生交换;所以下次扫描区间就可以由R[0..i] 缩减到[0..lastSwapPos]。

例如: 

              一组无序数:4,6,3,2,7,9,8

第一次排序完毕后是:4,3,2,6,7,8,第一次执行交换的位置为lastSwapPos=6

第二次排序完毕后是:3,2,4,6,78,9 第二次执行交换的位置为lastSwapPos=2

第二次执行交换的位置为lastSwapPos= 2,第3位,第4位没有执行交换,因为已经是有序,所以第三次交换的扫描区就可以有【0-4】变为【0-2】

代码如下

void maopao3(int a[], int size)  {      int lastSwapPos = 0;      for (int i = 0; i < size - 1; i++)      {          lastSwapPos 0;          for (int j = 1; j <lastSwapPos; j++)          {              if (a[j] > a[j + 1])              {                  int temp = a[j];                  a[j] = a[j+1];                  a[j+1] = temp;                    lastSwapPosTemp = j+1;              }          }          if (lastSwapPos == 0)              break;              }  }  

结语

以上是对于有特殊情况的无序数列,用冒泡排序法时候的优化,优化后程序的运行时间会明显减少。交换排序除了冒泡排序外,还有一种快速排序,实质上也是对冒泡排序的一种改进,下次我们再接着继续……

原创粉丝点击