初等排序之冒泡排序

来源:互联网 发布:淘宝新店引流量 编辑:程序博客网 时间:2024/05/29 14:57

   在看到第二章的排序算法,一直在纠结要不要写成博客,因为本来想着排序算法比较简单,而且真正的比赛时不会自己排序,都有封装的类库函数供自己使用,所以一开始不打算写成博客,可是我这个人有点追求完整,说的高大上一点就是追求完美,同时也想着学习也不仅仅是为了比赛和应付考试,所以还是打算写下这篇博客,之后的几篇博客也会围绕着排序算法来写。好了不多废话,开始~

   冒泡排序又叫起泡排序,是交换排序中最简单的排序方法,基本思想就是两两相邻的记录比较,在反序(指排列顺序与最终所需要的排序顺序相反)时则交换,正序则不变化。其余的也不多说,以一个例子进行形象的介绍:

初始数列:                                                   50 13 55 97 27 38 49 65

第一次比较:50>13 交换   ---------        50 13 55 97 27 38 49 65

第二次比较:50<=55 不交换 ---------    13 50 55 97 27 38 49 65

第三次比较:55<=97 不交换 ---------    13 50 55 97 27 38 49 65

第四次比较:97>27 交换 ---------          13 50 55 97 27 38 49 65

第五次比较:97>38 交换 ---------          13 50 55 27 97 38 49 65

第六次比较:97>49 交换 ---------          13 50 55 27 38 97 49 65

第七次比较:97>65 交换 ---------          13 50 55 27 38 49 97 65

第一趟比较结束,最终结果为                13 50 55 27 38 49 65 97


这里我们就可以看出冒泡排序的过程了,97在数列中最大,就像一个大气泡一样一路“过关斩将”,最终排到队列末尾,在第一趟结束后,也就使得使得有序区有了一个元素。

以下是每趟结果后数列的排序情况,在中括号中为无序区,中括号外为有序区:

初始数列:                                                        [50 13 55 97 27 38 49 65]

第一趟排序后:                                            [13 50 55 27 38 49 65] 97

第二趟排序后:                                             [13 50 27 38 49 55] 65 97

第三趟排序后:                                             [13 27 38 49 50] 55 65 97

第四趟排序后:                                             [13 27 38 49] 50 55 65 97

第五趟排序后:                                             [13 27 38] 49 50 55 65 97

第六趟排序后:                                             [13 27] 38 49 50 55 65 97

第七趟排序后:                                             [13] 27 38 49 50 55 65 97


在第七趟排序后,无序区只剩一个元素且在数列开头,这样整个数列就已经排序完成

接下来附上我的源码:

#include<stdio.h>void Bubble_Sort1(int A[],int N){for(int i=1;i<N;i++){  for(int j=0;j<N-i;j++)    if(A[j]>A[j+1])    {    int temp=A[j+1];    A[j+1]=A[j];    A[j]=temp;    }}}int main(){int N;int A[100];scanf("%d",&N);for(int i=0;i<N;i++)scanf("%d",&A[i]);Bubble_Sort1(A,N);for(int i=0;i<N;i++)printf("%d  ",A[i]);return 0;} 


思考:

   对于冒泡排序算法,有没有优化的地方呢,在上面第三趟之后,其实数列就已经是排序好的数列了,之后的每趟其实都没有在进行交换。

基于这点我们可以想到用一个变量记录exchange每趟最后一次交换,这个变量之后的数据已经排序好了,也就是有序区。

比如上面的第一趟排序后结果为[13 50 55 27 38 49 65] 97,在进行第二趟排序时,55分别与27,38,49进行交换,在遇到65时不进行交换,就变

成了第二趟的结果:[13 50 27 38 49 55] 65 97,如果我们这时用exchange记录最后一次交换,即55与49的交换,具体的记录方法是exchange为交换后的

49的下标,这时在包括下标为exchange+1的元素都是已经排序好的,也就是有序区55 65 97,因为之后没有交换,说明A[i]<=A[i+1](i=exchange+1,exchange+2.....n-1),

那么下趟的排序范围就从下标为0到exchange.

   下面为改进后的冒泡排序的数列每趟的结果:

初始数列:                                                        [50 13 55 97 27 38 49 65]    exchange=n-1=7,指向65

第一趟排序后:                                            [13 50 55 27 38 49 65] 97     exchange=6,指向65

第二趟排序后:                                             [13 50 27 38 49] 55 65 97    exchange=4,指向65

第三趟排序后:                                             [13 27 38 49 ]50 55 65 97      exchange=3,指向49

第四趟排序后:                                              13 27 38 49 50 55 65 97        exchange=0,结束

    同时我们可以看到,使用了这种方法后,在第二趟排序后,有序区比使用第一种方法多了一个元素,并且这种优势在第四趟体现的更加明显,直接排序完成。

以下是我的源码:

#include<stdio.h>void Bubble_Sort2(int A[],int N){int exchange=N-1;while(exchange){int end=exchange;            //end为无序区最后一个元素的下标 exchange=0;for(int i=0;i<end;i++){if(A[i]>A[i+1]){int temp=A[i+1];        A[i+1]=A[i];        A[i]=temp;          //exchange记录下最后一次交换中的前一个数的下标,之后都不交换,        exchange=i;         //exchange不会发生变化,说明包括exchange+1之后的已经排序好了 。 }}}}int main(){int N;int A[100];scanf("%d",&N);for(int i=0;i<N;i++)scanf("%d",&A[i]);Bubble_Sort2(A,N);for(int i=0;i<N;i++)printf("%d  ",A[i]);return 0;} 


PS:个人感觉写博客的时候把内容从头理了一边,挺好的,切勿急躁~
0 0
原创粉丝点击