关于冒泡排序

冒泡排序概念

冒泡排序是一种计算机科学领域的较简单的排序算法

它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果顺序(如从大到小、首字母从Z到A)错误就把他们交换过来。走访元素的工作是重复地进行,直到没有相邻元素需要交换,也就是说该元素列已经排序完成。

这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端(升序或降序排列),就如同碳酸饮料二氧化碳的气泡最终会上浮到顶端一样,故名“冒泡排序”。

冒泡排序原理

1.比较相邻的元素。如果第一个比第二个大,就交换他们两个。

2.对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数

3.针对所有的元素重复以上的步骤,除了最后一个。

4.持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

冒泡排序流程图

冒泡排序复杂度

时间复杂度(最优)

O(n)

时间复杂度(最坏)

O(n^2)

时间复杂度(平均)

O(n^2)

空间复杂度

O(1)

稳定性

稳定

平均复杂度的计算

循环

比较次数

第一次

(n-1)

第二次

(n-2)

第三次

(n-3)

......

......

最后一次

1

比较次数为:

(n-1) + (n-2) + (n-3) +.....+ 1 = n(n-1)/2

冒泡排序伪代码

  for(开始的索引i=0;  i <数组的长度;i++) {

           for(剩余未排序的索引j=0;  j < 当前未排序的长度; j++) {           

                  if(数组[j]>数组[j+1]) {

                         数组[j] 跟 数组[j+1] 调换位置

                  }
           }

 }

普通的冒泡排序

最简单的冒泡

数组:3,8,14,16,32,53
 public static void bubbleSort(int[] array){
         for(int i=0;i<array.length-1;i++){//控制比较轮次,一共 n-1 趟
             int num = 0; //用来记录比每轮比较的次数
             for(int j=0;j<array.length-1;j++){//控制两个挨着的元素进行比较
                 if(array[j] > array[j+1]){
                   //换位
                     int temp = array[j];
                     array[j] = array[j+1];
                     array[j+1] = temp;
                 }
                 //比较一次,加1
                 num =num+1;
 
             }
             //结果输出
             System.out.print("第"+(i+1)+"轮:[");
             for (int a=0;a<array.length; a++){
                 if(a!=array.length-1)
                 {
                     System.out.print(array[a]+",");
                 }else{
                     System.out.print(array[a]+"]");
                 }
             }
             System.out.println(",比较了:"+num+" 次");
         }
     }

结果

   第1轮结果:[3,14,16,32,8,53],每轮比较了:5 次
   第2轮结果:[3,14,16,8,32,53],每轮比较了:5 次
   第3轮结果:[3,14,8,16,32,53],每轮比较了:5 次
   第4轮结果:[3,8,14,16,32,53],每轮比较了:5 次
   第5轮结果:[3,8,14,16,32,53],每轮比较了:5 次

每一轮都比较了五次,但是到后面的比较,有一部分已经是排好了,如果某个数比他的下一个位置还小, 就没有必要和后面已经排好的数据再做比较。 比如第四轮,8和14比较,换位之后,16,32,53都已经排好了,14再和16比较,不用换位,那16之后的数据已经在第三轮排好,就没必要再比较16和32,32和53了。

普通的冒泡

我们就在程序内层循环做一个限制,每轮比较之后,下一轮就比较到array.length-1-i的位置。就是第一轮6位数都比较完成,最大排在最后,第二轮就比较前五个数,把前五个数中最大的排在第五位。这样以此类推,就可以减少程序中无用的比较。

public static void bubbleSort(int[] array){
         for(int i=0;i<array.length-1;i++){//控制比较轮次,一共 n-1 趟
             int num = 0; //用来记录比每轮比较的次数
             for(int j=0;j<array.length-1-i;j++){//控制两个挨着的元素进行比较
                 if(array[j] > array[j+1]){
                   //换位
                     int temp = array[j];
                     array[j] = array[j+1];
                     array[j+1] = temp;
                 }
                 //比较一次,加1
                 num =num+1;
 
             }
             //结果输出
             System.out.print("第"+(i+1)+"轮:[");
             for (int a=0;a<array.length; a++){
                 if(a!=array.length-1)
                 {
                     System.out.print(array[a]+",");
                 }else{
                     System.out.print(array[a]+"]");
                 }
             }
             System.out.println(",比较了:"+num+" 次");
         }
     }

冒泡排序1.0

优化轮次。

在经历过几轮比较交换后,剩下的数据不用在比较。我们可以用一个标志位来判断比较的结束。

for (int i = 0; i <arr.length-1; i++) {   //i 轮数
            System.out.println("目前是第"+(i+1)+"轮比较"); 
            //标志位
            boolean flag = true;
            for (int j = 0; j <arr.length-1-i ; j++) {   //j 次数
                System.out.println("第"+(i+1)+"轮,第"+(j+1)+"次比较");
                //交换的条件
                if(arr[j] > arr[j+1]){
                    int temp = arr[j+1];
                    arr[j+1] = arr[j];
                    arr[j] = temp;
                    flag = false;
                }
            }
            //输出当前轮次比较的结果
            System.out.println(Arrays.toString(arr));
 
            //当不再发生交换时,则结束比较
            if(flag){
                break;
            }
        }
        //输出
        System.out.println("排序后:"+Arrays.toString(arr));

冒泡排序2.0

假如数组为int[] arr = {4,6,3,7,8,9,10};

有一半的数据都不用再排序,应该

        //定义一个作为比较的边界
        int position = arr.length-1;
 
        for (int i = 0; i <arr.length-1; i++) {   //i 轮数
            System.out.println("目前是第"+(i+1)+"轮比较");
 
            //标志位
            boolean flag = true;
            //记录最后交换位置的值
            int limit = 0;
 
            for (int j = 0; j <position ; j++) {   //j 次数
                System.out.println("第"+(i+1)+"轮,第"+(j+1)+"次比较");
                //交换的条件
                if(arr[j] > arr[j+1]){
                    int temp = arr[j+1];
                    arr[j+1] = arr[j];
                    arr[j] = temp;
 
                    flag = false;
                    limit = j;
                }
            }
            position = limit;
            //输出当前轮次比较的结果
            System.out.println(Arrays.toString(arr));
 
            //当不再发生交换时,则结束比较
            if(flag){
                break;
            }
        }
        //输出
        System.out.println("排序后:"+Arrays.toString(arr));
    }
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值