冒泡排序算法

冒泡排序算法

冒泡排序(Bubble Sort),是一种计算机科学领域的较简单的排序算法。

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

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

算法原理

冒泡排序算法的原理如下:

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

算法分析

时间复杂度

若文件的初始状态是正序的,一趟扫描即可完成排序。所需的关键字比较次数C和记录移动次数均M达到最小值:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-n2h0Ex88-1625667467930)(https://bkimg.cdn.bcebos.com/formula/03e35724822180365d0d937fbc68b9b2.svg)] ,[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uxHWl0lw-1625667467932)(https://bkimg.cdn.bcebos.com/formula/9a569e56b84494c24acb31885c070f6f.svg)]。所以,冒泡排序最好的[时间复杂度为[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EiE4DtUb-1625667467935)(https://bkimg.cdn.bcebos.com/formula/f5a1886cf2ff13d73aee4d32d363f66e.svg)]。若初始文件是反序的,需要进行[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KoclsLXx-1625667467939)(https://bkimg.cdn.bcebos.com/formula/dd01d53f50293f756063f87e52c76000.svg)]趟排序。每趟排序要进行[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZuXaWixl-1625667467941)(https://bkimg.cdn.bcebos.com/formula/73cdbd7376481a2b19bc38c92d4dd9ff.svg)]

次关键字的比较(1≤i≤n-1),且每次比较都必须移动记录三次来达到交换记录位置。在这种情况下,比较和移动次数均达到最大值:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vkBLpWNF-1625667467943)(https://bkimg.cdn.bcebos.com/formula/51947f4116d1beb324f5a061dac8edbd.svg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eT4Cajkk-1625667467943)(https://bkimg.cdn.bcebos.com/formula/2cfa295e83cce099e1ff5afd4f0ba50d.svg)]

冒泡排序的最坏时间复杂度为[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EEB8CJvq-1625667467944)(https://bkimg.cdn.bcebos.com/formula/93e1a5d467b4fce05210acb873107e09.svg)]。

综上,因此冒泡排序总的平均时间复杂度为[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HMITL1GT-1625667467945)(https://bkimg.cdn.bcebos.com/formula/93e1a5d467b4fce05210acb873107e09.svg)]。

算法稳定性

冒泡排序就是把小的元素往前调或者把大的元素往后调。比较是相邻的两个元素比较,交换也发生在这两个元素之间。所以,如果两个元素相等,是不会再交换的;如果两个相等的元素没有相邻,那么即使通过前面的两两交换把两个相邻起来,这时候也不会交换,所以相同元素的前后顺序并没有改变,所以冒泡排序是一种稳定排序算法。

算法描述

public static void bubbleSort(int arr[]) {
    for(int i =0 ; i<arr.length-1 ; i++) { 
        for(int j=0 ; j<arr.length-1-i ; j++) {  
            if(arr[j]>arr[j+1]) {
                int temp = arr[j];
                arr[j]=arr[j+1];
                arr[j+1]=temp;
        	}
        }    
    }
}

优化

  • 针对问题:

数据的顺序排好之后,冒泡算法仍然会继续进行下一轮的比较,直到arr.length-1次,后面的比较没有意义的。

  • 方案:

设置标志位flag,如果发生了交换flag设置为true;如果没有交换就设置为false。

这样当一轮比较结束后如果flag仍为false,即:这一轮没有发生交换,说明数据的顺序已经排好,没有必要继续进行下去。

public static void BubbleSort1(int [] arr){
    int temp;//临时变量
    boolean flag;//是否交换的标志
    for(int i=0; i<arr.length-1; i++){//表示趟数,一共 arr.length-1 次
        //每次遍历标志位都要先置为false,才能判断后面的元素是否发生了交换
        flag = false;
        for(int j=arr.length-1; j>i; j--){ //选出该趟排序的最大值往后移动
            if(arr[j] < arr[j-1]){
                temp = arr[j];
                arr[j] = arr[j-1];
                arr[j-1] = temp;
                flag = true;//只要有发生了交换,flag就置为true
            }
        }
        //判断标志位是否为false,如果为false,说明后面的元素已经有序,就直接return 
        if(!flag) break;
    }
 }

算法比较

排序算法平均时间复杂度
冒泡排序O(n²)
选择排序O(n²)
插入排序O(n²)
希尔排序O(n1.5)
快速排序O(N*logN)
归并排序O(N*logN)
堆排序O(N*logN)
基数排序O(d(n+r))

插入排序

​ 插入排序算法是基于某序列已经有序排列的情况下,通过一次插入一个元素的方式按照原有排序方式增加元素。这种比较是从该有序序列的最末端开始执行,即要插入序列中的元素最先和有序序列中最大的元素比较,若其大于该最大元素,则可直接插入最大元素的后面即可,否则再向前一位比较查找直至找到应该插入的位置为止。插入排序的基本思想是,每次将1个待排序的记录按其关键字大小插入到前面已经排好序的子序列中,寻找最适当的位置,直至全部记录插入完毕。执行过程中,若遇到和插入元素相等的位置,则将要插人的元素放在该相等元素的后面,因此插入该元素后并未改变原序列的前后顺序。我们认为插入排序也是一种稳定的排序方法。插入排序分直接插入排序、折半插入排序和希尔排序3类。

选择排序

​ 选择排序算法的基本思路是为每一个位置选择当前最小的元素。选择排序的基本思想是,基于直接选择排序和堆排序这两种基本的简单排序方法。首先从第1个位置开始对全部元素进行选择,选出全部元素中最小的给该位置,再对第2个位置进行选择,在剩余元素中选择最小的给该位置即可;以此类推,重复进行“最小元素”的选择,直至完成第(n-1)个位置的元素选择,则第n个位置就只剩唯一的最大元素,此时不需再进行选择。使用这种排序时,要注意其中一个不同于冒泡法的细节。举例说明:序列58539.我们知道第一遍选择第1个元素“5”会和元素“3”交换,那么原序列中的两个相同元素“5”之间的前后相对顺序就发生了改变。因此,我们说选择排序不是稳定的排序算法,它在计算过程中会破坏稳定性。

快速排序

​ 快速排序的基本思想是:通过一趟排序算法把所需要排序的序列的元素分割成两大块,其中,一部分的元素都要小于或等于另外一部分的序列元素,然后仍根据该种方法对划分后的这两块序列的元素分别再次实行快速排序算法,排序实现的整个过程可以是递归的来进行调用,最终能够实现将所需排序的无序序列元素变为一个有序的序列。

归并排序

​ 归并排序算法就是把序列递归划分成为一个个短序列,以其中只有1个元素的直接序列或者只有2个元素的序列作为短序列的递归出口,再将全部有序的短序列按照一定的规则进行排序为长序列。归并排序融合了分治策略,即将含有n个记录的初始序列中的每个记录均视为长度为1的子序列,再将这n个子序列两两合并得到n/2个长度为2(当凡为奇数时会出现长度为l的情况)的有序子序列;将上述步骤重复操作,直至得到1个长度为n的有序长序列。需要注意的是,在进行元素比较和交换时,若两个元素大小相等则不必刻意交换位置,因此该算法不会破坏序列的稳定性,即归并排序也是稳定的排序算法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值