算法系列(二):冒泡排序

174 阅读3分钟

冒泡排序介绍:

冒泡排序(Bubble Sort),是一种计算机科学领域的较简单的排序算法。 它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。 这个算法的名字由来是因为越大的元素会经由交换慢慢“浮”到数列的顶端,故名;

冒泡排序过程:

冒泡排序算法的运作如下:(从后往前)

  1. 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
  2. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
  3. 针对所有的元素重复以上的步骤,除了最后一个。
  4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

冒泡排序算法代码如下:

package com.nineweeks.simplesort;

/**
 *
 * 冒泡排序
 *
 * 规则:从左边开始 拿第一个值 和 右边的值相比,如果
 * ①左边的值<右边的值,则什么也不做,
 * ②左边的值 >=右边的值,则两个值互换位置
 * ③下标往右移一个位置,开始从当前位置,和右边相邻的比较
 *
 * 冒泡排序,每经历一次循环,能够确定最右边的值在准确的位置
 *
 *
 * 冒泡排序的时间复杂度
 * 第一次循环需要 进行n次比较,第二次循环需要n-1次比较,以此类推,知道最后一次比较1次
 * ,所以总的比较次数为n(n-1)/2
 *     大O表达式:O(n2);n的平方
 * 因为只在需要时,才进行交换,如果数字是随机的,平均的交换概率为1/2,有n(n-1)/2次比较,
 * 就会有n(n-1)/4次的交换
 * 所以冒泡排序的交换时间复杂度:
 *     大O表达式:O(n2);n的平方
 *
 *
 * @author NineWeek
 * @date 2020/05/07 16:10
 **/
public class BubbleSort {
    private long[] a;
    private int nElems;

    public BubbleSort(int max){
        a = new long[max];
        nElems = 0;
    }

    public void insert(long value){
        a[nElems++] = value;
    }

    public void bubbleSort(){
        int in,out;
        for (out = nElems-1;out > 0; out--){
            for (in = 0; in < out;in++){
                if(a[in] > a[in +1]){
                    swap(in,in+1);
                }
            }
        }
    }

    private void swap(int one, int two) {
        long temp;
        temp = a[one];
        a[one] = a[two];
        a[two] = temp;
    }

    /**
     * 数组的展示方法
     */
    public void display(){
        for (int i = 0; i < nElems ; i++) {
            System.out.print(a[i]+" ");
        }
        System.out.println();
    }

    public  static  void main(String[] args){
        BubbleSort  sort = new BubbleSort(100);
        sort.insert(77);
        sort.insert(99);
        sort.insert(44);
        sort.insert(55);
        sort.insert(22);
        sort.insert(88);
        sort.insert(11);
        sort.insert(80);
        sort.insert(66);
        sort.insert(33);
        sort.insert(10);
        sort.display();
        System.out.println("======================");
        sort.bubbleSort();
        sort.display();
    }

}

数据输出如下

时间复杂度分析:

若文件的初始状态是正序的,一趟扫描即可完成排序。所需的关键字比较次数 C和记录移动次数 M均达到最小值:Cmin = n-1,Mmin = 0。 所以,冒泡排序最好的时间复杂度为O(n)

若初始文件是反序的,需要进行 n-1趟排序。每趟排序要进行n-i次关键字的比较(1≤i≤n-1),且每次比较都必须移动记录三次来达到交换记录位置。在这种情况下,比较和移动次数均达到最大值:

Cmax = \frac{n(n-1)}{2} =O(n^2)
Max = \frac{3n(n-1)}{2}=O(n^2)

冒泡排序的最坏时间复杂度为 O(n^2) 。 综上,因此冒泡排序总的平均时间复杂度为O(n^2)