代码改变世界

算法与数据结构——排序(二)冒泡排序(中)

2012-10-18 07:50  左眼微笑右眼泪  阅读(507)  评论(0编辑  收藏  举报

    上一种冒泡算法,是从数组的第一个位置开始,把每个位置的数与其他剩下的数进行比较,如果后面的数有比它小的(或者大的,下面都以小的为例)就进行交换。通过分析这个过程,可以知道,这种算法,每次冒泡的结果都是把所有数里面最小的那一个提到了最前面,而其他的数的顺序都是杂乱无章的。第二次就把第二小的数提取到最前面。每次排序后,对后面的排序都没有帮助。我们就会想,有没有一种排序的算法在把最小的提到前面去的过程中,也能把第二小或者第三小的顺序往前面挪一点呢?这样的话,我们在第二次排序的时候,交换的次数就会减少。下面的冒泡排序就是这样的一种方法。它前一次排序的结果可以给后一次排序带来一定的帮助。它的主要思路如下:

    1.从第一个数开始,从左到右,把相邻的两个数进行比较,如果如果后面的一个数比前面的一个数小,那么就交换它们的位置,否则的话,就不用交换。第一次循环完成后,我们会发现,最大的数9已经排在最后面了,而第二在的数8已经排在倒数第二位了。(如果用前面的排序方法就得不到这样的结果);

    2.还是从第一个数开始,从左到右,把相邻的两个数进行比较,如果后面的数比前面的数小,那么就交换位置。但注意第二次比较,只用比较到数组的倒数第二个位置就可以了。因为通过第一次比较,已经把数组里面最大的数放在了数组的最后一位,所以在第二次比较的时候,就不用跟最后一位进行比较了。

   3.同理,还是从第一个数开始进行比较,比较到倒数第三个数为止。……一直到最后,只需要比较第一个数和第二个数了。

     下面是第一次比较和第二次比较的一个示例图。

 

image

image

 

 

 

 

 

 

 

 

 

 

 

   下面来看具体的实现代码:

public List<int> BubleSort(List<int> sortList)
     {
         for (int i = 0; i < sortList.Count; i++)
         {
             //方法一,把最大的放到数组的尾部
             for (int j = 0; j < sortList.Count - i - 1; j++)
             {
                 if (sortList[j] > sortList[j + 1])
                 {
                     int temp = sortList[j];
                     sortList[j] = sortList[j + 1];
                     sortList[j + 1] = temp;
                 }
             }
 
             //方法二,把最大的数放到数组的头部
             //for (int j = sortList.Count - 2; j >=i; j--)
             //{
             //    if (sortList[j] > sortList[j + 1])
             //    {
             //        int temp = sortList[j];
             //        sortList[j] = sortList[j + 1];
             //        sortList[j + 1] = temp;
             //    }
             //}
 
         }
         return sortList;
     }

    根据上面的思路,理解这段代码应该很容易了。在这里面,第二个for循环有两种写法,一种是每次把最大的数移动到最后面,还有一种就是每次把最大的数移动到最前面。

     这种排序算法还有没有改进的地方呢?如果我们的排序序列是一个有序的序列,那么你会发现,比较的次数还是会和处理其他序列一样多,这样是不是有点多余,要知道多比较一次耗费的时间就多一点,如果处理非常多的数据,这就会影响效率。我们思考下,看看还有没有其他的改进方法呢?