• 冒泡排序及优化


    先上一段代码

    1 for (i=1;i<n;i++)
    2   for (j=1;j<=n-i;j++)
    3     if (a[j]<a[j+1])
    4      {
    5           t=a[j];
    6           a[j]=a[j+1];
    7           a[j+1]=t;
    8      } 

    这是用冒泡排序对一个无序数组从大到小排序

    通过n-1轮比较、交换

    每一轮从数组最前面的两个开始比较

    相邻两个比较

    因为最后排完序是从大到小

    所以最后排在前面的数一定比排在后面的数大

    所以相邻两个比较的时候如果前面的比后面的小

    说明它们的相对位置不符合排序后的最终相对位置

    就把它们交换

    每一轮交换会把一个最小的数移到最后

    n-1轮交换之后就排好序了

    比如

    93 85 77 68 59 100 43 94 75 82

    从大到小排

    先比较最前面的两个数,即93 和85

    发现93>85符合最终顺序

    它们的相对位置没问题

    然后继续比较85和77

    还是没问题

    再比77和68

    没问题

    比到59和100的时候

    就有问题了

    因为59比100小

    所以就交换这两个数

    就变成

    93 85 77 68 100 59 43 94 75 82

    然后继续比

    比到43和94

    又有问题

    就再交换

    变成

    93 85 77 68 100 59 94 43 75 82

    然后比43和75

    交换

    变成

    93 85 77 68 100 59 94 75 43 82

    然后比43和82

    再交换

    变成

    93 85 77 68 100 59 94 75 82 43

    这样第一轮就比完了

    现在数组里面最后一个数是43

    这个数是数组里面最小的

    排完序后它的位置一定在最后一个

    不会再变了

    所以接下来就不用管它

    下一轮只要给前n-1个排序

    93 85 77 68 100 59 94 75 82 43

    以此类推

    93 85 77 100 68 59 94 75 82 43

    93 85 77 100 68 94 59 75 82 43

    93 85 77 100 68 94 75 59 82 43

    93 85 77 100 68 94 75 82 59 43

    第二轮比完之后第二小的会移到n-1的位置

    93 85 77 100 68 94 75 82 59 43

    然后最后两个数的位置就不会再变了

    第三轮只要给前n-2个数排序

    93 85 100 77 68 94 75 82 59 43

    93 85 100 77 94 68 75 82 59 43

    93 85 100 77 94 75 68 82 59 43

    93 85 100 77 94 75 82 68 59 43

    93 85 100 77 94 75 82 68 59 43

    ……

    第i轮比完最后会有i个数的位置确定了

    所以  for (j=1;j<=n-i;j++)

    而外面那个 for (i=1;i<n;i++) 表示比较了n-1轮

    这个过程就像每次让最轻的泡泡一点一点升到最上面

    所以这个排序算法叫做冒泡排序

    n-1轮后,会有n-1个数的位置确定了

    那么剩下第n个数的位置也确定了

    所以只需比较n-1轮

    冒泡排序时间复杂度是O(n2),对于较大的数据会超时

    有一个小小的优化感觉时间也没快多少

    我们知道经过n-1轮比较、交换后,会得到一个有序数组,但事实上可能只需要i(i<n-1)轮数组就已经有序了,那么i+1→n-1轮的比较就没有必要了,我们可以通过去掉这几轮的比较以减少时间

    而对于每一轮的比较,都是比较相邻的两个数,如果某一轮比较没有交换任何两个数,说明此时数组已经有序了,以从大到小排序为例,如果一轮比较后没有交换任何两个数,说明任何两个相邻的数的相对位置都符合排序后的最终相对位置,即,对于任意j(1<=j<=n-i),必满足a[j]>a[j+1](否则就会发生交换),所以此时就可以退出循环了

    我们可以设一个标记flag,每一轮开始时将flag赋为false,在这一轮的循环比较中一旦发生交换就把flag赋成true,一轮循环结束后检验flag的值是否为true,若依然为false则说明数组已经有序,可以直接跳出接下来i+1→n-1轮的比较

     

     1 for (i=1;i<n;i++)
     2 {
     3     flag=0;
     4     for (j=1;j<=n-i;j++)
     5     {
     6         if (a[j]<a[j+1])
     7         {
     8             t=a[j];
     9             a[j]=a[j+1];
    10             a[j+1]=t;
    11             flag=1;
    12         }
    13     }
    14     if (!flag) break;
    15 }
  • 相关阅读:
    利用合成数据进行时间序列分类的数据扩充方法
    基于 KubeSphere CI/CD 将 Spring Boot 项目发布至 Kubernetes
    矩阵白化
    delphi 过滤开头 结尾 全部 空格的函数
    delphi CopyFileProgressBar 拷贝文件显示进度条
    delphi 分享三个随机字符串
    delphi IsIPAdress 非正则表达式验证IP的方法
    delphi PosAnsi
    delphi公用函数
    Delphi中break,exit,abort跳出循环的比较
  • 原文地址:https://www.cnblogs.com/rabbit1103/p/14018105.html
Copyright © 2020-2023  润新知