zoukankan      html  css  js  c++  java
  • 冒泡排序

        冒泡排序的时间复杂度为O(n2),虽然很多排序的时间复杂度都是O(n2),但是冒泡排序的O(n2)则显得非常比较大。

        简单的说,一般情况下,冒泡排序是很不好的排序,非常慢,但是作为排序算法的入门算法,它的基本思想很是重要。

        冒泡排序是交换排序的一种,需要两层循环,以升序排序为例,

        第一次循环把最第1大值放在序列倒数第1的位置

        第一次循环把最第2大值放在序列倒数第2的位置

        第一次循环把最第3大值放在序列倒数第3的位置

          ......

        第一次循环把最第n大值放在序列倒数第n的位置

        下面给出实现:

    void bubble_sort(int *array,int n)
    {
        assert(array);
        int i,j;
    
        for(i=0;i<n;i++)
            for(j=1;j<n-i;j++)//要保证索引 j-1 和 j 不越界
                if(array[j-1]>array[j])//大的往后移 
                    swap(array[j-1],array[j]);
    }

        在很多情况下,第一层循环还未循环完,序列就已经顺序了,这个时候就可以退出函数,而不是等第一层循环完在退出函数

     当第二层循环不发生元素交换,那么说明序列已经顺序,用swapped记录是否发生交换

    //冒泡 一改 
    void bubble_sort1(int *array,int n)
    {
        assert(array);
        int swapped=1;
        int i,j;
        
        for(i=0;i<n&&swapped;i++)
        {
            swapped=0;
            for(j=1;j<n-i;j++)
                if(array[j-1]>array[j])//大的往后移 
                {
                    swapped=1;//发生过交换
                    swap(array[j-1],array[j]);
                }
        }
    }

        前面都是把元素从头往后排序,也就是把大的元素往后放,同样的,把小的元素往前放,也能实现同样的排序。

        那么往前放和往后放有什么区别呢?

        对于序列    2 3 1 4

        对于正排   2 3 1 4-->2 1 3 4-->1 2 3 4需要循环2次

        对于逆排   2 3 1 4-->1 2 3 4需要循环1次

     1 //冒泡 二改
     2 void bubble_sort2(int *array,int n)
     3 {
     4     assert(array);
     5     int i,j;
     6     
     7     for(i=0;i<n;i++)
     8     {
     9         for(j=1;j<n-i;j++)
    10             if(array[j-1]>array[j])//大的往后移 
    11                 swap(array[j-1],array[j]);
    12         for(j=n-i-2;j>i;j--)
    13             if(array[j-1]>array[j])//小的往前移
    14                  swap(array[j-1],array[j]);
    15     }
    16 }

        综合bubble_sort1和bubble_sort2,有

     1 //冒泡 三改
     2 void bubble_sort3(int *array,int n)
     3 {
     4     assert(array);
     5     int i,j;
     6     int swapped=1;
     7     
     8     for(i=0;i<n&&swapped;i++)
     9     {
    10         swapped=0;
    11         for(j=1;j<n-i;j++)
    12             if(array[j-1]>array[j])//大的往后移 
    13             {
    14                 swap(array[j-1],array[j]);
    15                 swapped=1;
    16             }
    17         if(0==swapped)
    18             break;
    19         for(j=n-i-2;j>i;j--)
    20             if(array[j-1]>array[j])//小的往前移
    21             {
    22                  swap(array[j-1],array[j]);
    23                  swapped=1;
    24             }
    25     }
    26 }

        下面对这四个函数进行实际测试

    #include<stdio.h>
    #include<stdlib.h>
    #include<time.h>
    #include<assert.h>
    
    #define swap(a,b) (a^=b,b^=a,a^=b)
    #define N 100000
    
    void print(int *,int);
     
    int main()
    {
        int a[4][N];
        int i;
        int beg,end;
        //定义一个存储4个函数指针的数组
        void (*sort[4])(int *,int n)={bubble_sort,bubble_sort1,bubble_sort2,bubble_sort3};
        char *str[4]={"bubble_sort ","bubble_sort1","bubble_sort2","bubble_sort3"};
        
        srand((unsigned)time(NULL));
        printf("正在生成数组...
    ");
        beg=clock();
        for(i=0;i<N;i++)//生成数组的每个元素 
        {
            a[0][i]=rand()%90+10;//元素范围为[10,99]
            a[1][i]=rand()%90+10;
            a[2][i]=rand()%90+10;
            a[3][i]=rand()%90+10;
        }
        end=clock();
        printf("生成数组完毕,用时 %lfs
    ",(double)(end-beg)/CLOCKS_PER_SEC);
        //print(a[0],N);
        
        for(i=0;i<4;i++)
        {
            beg=clock();
            sort[i](a[i],N);
            end=clock();
            //print(a[i],N);
            printf("%s花费时间为 %lfs
    ",str[i],(double)(end-beg)/CLOCKS_PER_SEC);
        }
        
        getchar();
        return 0;
    }
    
    void print(int *array,int n)
    {
        int i;
        for(i=0;i<n;i++)
            printf("%d ",array[i]);
        printf("
    ");
    }

        运行结果如下:

        对长度为10万的基本整形数组排列后,二改的效率反而降低,这是因为要进行正向排序和逆向排序,导致内层循环从一个变到了两个,增加了循环次数。

        一改和原算法效率并没有多大提升,有的时候效率反而还略微不如以前,这是因为一改的算法增加了许多次int的赋值,但是减少了很多次元素的比较,在一些比较元素很费时(比如给字符串们排序)的排序中,一改的优越性马上就会体现出来。

        显然三改后的算法是四者中最好的。

  • 相关阅读:
    在ubuntu下关闭笔记本触摸板
    (转载)实用小命令 windows下查看端口占用情况
    (转载)JBoss 4.2.3下部署EJB 3.0碰到的local和remote问题
    Windows下通过xmanager远程桌面控制Linux(转)
    SQL Server 事务日志的问题
    回归
    用友软件工程IT应用研究院
    关于Oracle数据库的死锁(转书摘)
    关于企业级Web2.0的一点想法
    关注Java的开源项目(中文版)
  • 原文地址:https://www.cnblogs.com/inori/p/4985678.html
Copyright © 2011-2022 走看看