图解冒泡排序算法

  • 冒泡排序算法的思想 
    冒泡排序,听名字,顾名思义就是像泡泡一样,大的泡泡就冒的快,排在最上面,最容易冒出水面。我们运用这个思路,对我们的算法进行分析。
    首先,假定有如下图这样一排大小不一的圆,编号1、2、3、4,混乱排列。
    
    我们先指定一个比较顺序,比如上图的从左边往右边比较,也就是2号圆和3号圆比较大小,结果是2号圆大于3号圆,也就是左大于右。这个时候,按照冒泡规则,大的就要往前排了,所以这个时候我们要进行一个交换操作,也就是2号圆和3号圆交换位置,结果如下图:

    当然,你也可以执行左小于右交换的规则,这就要看你是排顺序还是倒序了。接下来,我们再拿2号圆与1号圆进行比较,很明显,2号圆小于1号圆,结果就是不进行交换,如图:

    然后最后进行1号圆与4号圆的比较,1号圆大于4号圆,进行交换,得到结果如图:

    这个时候,我特意把1号圆标成了红色,因为这一趟比较下来,1号圆,也就是最大的圆,已经到了最右边了,就像冒泡泡一样,最大的泡泡已经出水面了。那么接下来,就是在剩下的2、3、4号圆里面选出最大的,规则就跟上面的一样,大于就交换位置,往右排,每一轮比较完的结果如下图:


    经过三趟的排序,这个序列就排序好了。
  • 代码实现
    好了,上面的原理讲好了,那代码怎么实现呢?
    
int temp = 0;
for ( int i = 0; i < attr. length - 1; i++) {
     for ( int j = 0; j < attr. length - i - 1; j++) {
         if (attr[j] > attr[j + 1]) {
           temp = attr[j];
           attr[j] = attr[j + 1];
           attr[j + 1] = temp;
        }
    }
}
    以上代码块就是冒泡排序的核心代码了,第二行中的attr.length-1(n-1)是总共执行的趟数,第三行的attr.length-i-1则是在第i趟,需要比较的次数。为啥是attr.length-i-1,这里可以这样理解,第i趟时,已经排好序的个数就是i(注意这里i从0开始)。也就是说这i个数是不用比较的,所以要减去。然后又因为每趟比较的次数是需比较的总数减去1,所以第二个循环里面就是attr.length-i-1了。

  • 时间复杂度
    根据上面的分析,我们就可以发现,4个数时,我们要执行3趟,总共需要比较的次数为3+2+1次,如果推广到数量为n的规模,就是(n-1)+(n-2)+(n-3)+...+2+1,这很明显就是一个等差数列了,求和为:((n-1)+1)(n-1)/2=n(n-1)/2= n^2/2-n/2
     根据复杂度的规则,去掉低阶项(也就是n/2),并去掉常数系数,那复杂度就是O(n^2)了
  • 稳定性
    稳定性: 当你原来待排的元素中间有相同的元素,在没有排序之前它们之间有先后顺序,在排完后它们之间的先后顺序不变,我们就称这个算法是稳定的。
    根据稳定性的定义,结合我们的代码段 attr[j] > attr[j + 1],只有在大于的情况我们才会进行交换,等于的情况不会交换位置,所以我们可以说冒泡排序是一个稳定的排序。

猜你喜欢

转载自blog.csdn.net/qq_14904791/article/details/79036045