排序算法系列:详解冒泡排序算法及其java实现

414 阅读4分钟

这是我参与11月更文挑战的第2天,活动详情查看:2021最后一次更文挑战

作者的其他平台:

| CSDN:blog.csdn.net/qq_4115394…

| 掘金:juejin.cn/user/651387…

| 知乎:www.zhihu.com/people/1024…

| GitHub:github.com/JiangXia-10…

| 公众号:1024笔记

本文大概970字,读完共需4分钟

一、算法思想

冒泡排序是一种交换排序算法,元素通过两两的比较,交换不满足次序要求的元素,直到整个数组都满足次序要求为止。

比如一个无序的数组中有元素[4,3,8,6,1],如果按照升序的排序顺序,则采用冒泡排序的过程则是:

第一趟排序:先是4和3比较,4比3大,则交换位置,则顺序是

                      3 4 8 6 1

然后4和8比较,8比4大,则不交换顺序,顺序还是

                      3  4 8 6 1

然后8和6比较,8比6大,则交换顺序,则顺序是

                      3  4 6  8 1

然后 8 和 1 比较 8 比1 大,则交换顺序,则顺序是

                      3  4 6 1 8

所以第一趟排序的最终结果是3 4 6 1 8,即最大的元素在最后的位置。

第二趟排序:3 和 4 比较,3 比 4小,不交换顺序,顺序不变

4 和 6 比较,4 比6 小,不交换顺序,顺序不变

6 和 1 比较,6 比 1 大,交换顺序,则顺序为 3 4 1 6 8,

6 和 8 比较,6 比 8 小,不交换顺序,则顺序为3 4 1 6 8

所以第二趟的排序结果为3 4 1 6 8,即第二大的元素在倒数第二的位置

第三趟排序  3 和 4 比较 不交换顺序

4 和 1 比较 交换顺序,交换后顺序为3 1 4 6 8

。。。。后面已经为顺序了,交换顺序不变,

所以第三趟的排序为3 1 4 6 8,即第三大的顺序在倒数第三的位置

第四趟排序   3 和 1 比较,交换顺序,交换后排序为 1 3 4 6 8,

经过四趟排序,数组为顺序数组。

二、算法分析

通过上述演示,我们可以发现当长度为N的数组的初始状态是顺序的,则一趟排序即可完成排序。比较次数为N-1和记录移动次数为0,均为最小值。所以,冒泡排序最好时间复杂度为O(N)。
当数组的初始顺序是倒叙的,则需要进行 N -1 趟排序。每趟排序要进行 N - i 次关键字的比较(1 ≤ i ≤ N - 1),每次比较都必须移动记录三次来达到交换记录位置。比较和移动次数均达到最大值N^2,所以冒泡排序的最坏时间复杂度为O(N^2)。
所以,冒泡排序的平均时间复杂度为O(N^2)。 当两个元素大小相等时,相对位置不会发生改变,所以冒泡排序是稳定的排序算法

三、Java代码

import java.util.Arrays;
/**
 * @Author: 江夏
 * @Date: 2021/11/02/20:50
 * @Description:冒泡排序算法
 */
public class MaoPaoSort {
    public static void main(String[] args) {
        int testTime=500000;
        int size = 10;
        int value=100;
        boolean succeed = true;
        for(int i = 0 ;i<testTime;i++){
            int[] arr1 = generateRandomArray(size,value);
            int[] arr2 = copyArray(arr1);
            int[] arr3= copyArray(arr1);
            bubbleSort(arr1);
            rightMethod(arr2);
            if(!isEqual(arr1,arr2)){
                succeed=false;
                printArray(arr3);
                break;
            }
        }
        int[] arr= generateRandomArray(size,value);
        printArray(arr);
        bubbleSort(arr);
        printArray(arr);
    }
    //产生一个随机数组,数组的长度和值都是随机的,
    public static  int[] generateRandomArray(int size,int value){
        int[] arr = new int[(int)((size+1)*Math.random())];
        for(int i = 0 ;i<arr.length;i++){
            //值也可以是随机的
            arr[i]=(int)((value+1)*Math.random())-(int)(value*Math.random());
        }
        return arr;
    }
    //复制数组
    public static int[] copyArray(int[] arr){
        if(arr==null){
            return null;
        }
        int[] res = new int[arr.length];
        for(int i = 0 ;i<arr.length;i++){
            res[i]=arr[i]  ;
        }
        return res;
    }
    public static void rightMethod(int[] arr){
        Arrays.sort(arr);
    }
    public static boolean isEqual(int[] arr1,int[] arr2){
        if(arr1==null&&arr2!=null||arr1!=null&&arr2==null){
            return false;
        }
        if (arr1==null&&arr2==null){
            return true;
        }
        if (arr1.length!=arr2.length){
            return false;
        }
        for(int i = 0;i<arr1.length;i++){
            if(arr1[i]!=arr2[i]){
                return false;
            }
        }
        return true;
    }
    //打印出数组
    public static void printArray(int[] arr){
        if(arr==null){
            return;
        }
        for(int i = 0 ;i<arr.length;i++){
            System.out.print(arr[i]+" ");
        }
        System.out.println();
    }

    //N个数字冒泡排序,总共要进行N-1趟比较,每趟的排序次数为(N-i)次比较
    public static void bubbleSort(int[] arr){
        if(arr==null||arr.length<2){
            return;
        }
        //需要进行arr.length趟比较
        for(int i = 0 ;i<arr.length-1;i++){
            //第i趟比较
            for(int j = 0 ;j<arr.length-i-1;j++){
                //开始进行比较,如果arr[j]比arr[j+1]的值大,那就交换位置
                if(arr[j]>arr[j+1]){
                    int temp=arr[j];
                    arr[j]=arr[j+1];
                    arr[j+1]=temp;
                }
            }
        }
    }
    public static  void rightMathods(int[] arr){
        //调用系统调用的函数来进行验证
        Arrays.sort(arr);
    }
}

运行结果如下:

image.png

四 总结

冒泡排序原理就是比较两个相邻的元素,将值大的元素交换到右边,因为这种排序相等的元素不进行交换,所以它是一种稳定排序

冒泡排序的优点:每进行一趟排序,就会少比较一次,因为每进行一趟排序都会找出一个较大值。一定程度上减少了算法的量。

如果元素刚好都是正序排序,只需要走一趟即可完成排序。所需的比较次数C和记录移动次数M均达到最小值,即:Cmin=n-1;Mmin=0;所以,冒泡排序最好的时间复杂度为O(n)。

如果元素都是反序排序,则需要进行n-1趟排序。每趟排序要进行n-i次比较(1≤i≤n-1),且每次比较都必须移动记录三次来达到交换记录位置。在这种情况下,比较和移动次数均达到最大值:     image.png

所以冒泡排序总的平均时间复杂度为:O(n2)(n的平方)。

以上就是关于冒泡排序的介绍!

其他推荐: