冒泡排序

面试中很多笔试题都有冒泡排序的算法,今天我就整理一下。

1、定义

百度百科:

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

它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果顺序(如从大到小、首字母从从Z到A)错误就把他们交换过来。走访元素的工作是重复地进行直到没有相邻元素需要交换,也就是说该元素列已经排序完成。
这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端(升序或降序排列),就如同碳酸饮料中二氧化碳的气泡最终会上浮到顶端一样,故名“冒泡排序”。
 
2、原理
  1. 比较相邻的元素。如果第一个比第二个大,就交换他们两个。 
  2. 对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
  3. 针对所有的元素重复以上的步骤,除了最后一个。
  4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

3、时间复杂度:O(N^2)

4、代码示例

1、根据原理简单实现

 

public int[] bubbleSort1(int[] initArr){
    if(initArr.length > 1){
        for(int i =0; i < initArr.length; i++){
            for(int j =0; j < initArr.length-i-1; j++){
                if(initArr[j] > initArr[j+1]){
                    int temp = initArr[j];
                    initArr[j] = initArr[j+1];
                    initArr[j+1] = temp;
                }
            }
        }
    }
    return initArr;
}

 

以上采用双循环方式,外层表示循环次数,内层表示实际操作的相关处理。

2、简单优化策略
采用以上循环策略,方法会机械的执行,即使在某一次执行后他已经完成排序了,如下图所示,第六次排序已经获取到了最终结果,可是他还要重复执行第七、八轮排序。
图片来自网络,侵删
 
 
/**
  *简单优化:如果在某一轮已经能获取正确结果,无需之后的排序
     * 原理:在方法一的基础上,通过添加标记符isSort,如果有位置交换就说明是无序的,否则是有序的
     * @param initArr
  */
public int[] bubbleSort2(int[] initArr){
    if(initArr.length > 1){
        for(int i =0; i < initArr.length; i++){
            boolean isSorted = true;
            for(int j =0; j < initArr.length-i-1; j++){
                if(initArr[j] > initArr[j+1]){
                    int temp = initArr[j];
                    initArr[j] = initArr[j+1];
                    initArr[j+1] = temp;
                    isSorted = false;
                }
            }
            if(isSorted){
                break;
            }
        }
    }
    return initArr;
}

 


4、进阶优化
如图一个新的待排序数组,我们可以发现后面四个无需排序,只有前面四个才需要排序。
图片来源于网络,侵删。

 

如果以上我们可以定义一个排序边界(sortBorder)用来区分:有序去和无序区。 

如何定义这个边界?我们可以记录每次交换的最后一个元素位置,那么这个位置就可以认为是边界位置。

/**
 * 进阶优化:定义有序区和无序区,只排序无序区的元素
 * 原理:通过记录最后一次交换元素的位置,把这个位置默认成无序区和有序区的边界
 * @param initArr
 */
public int[] bubbleSort3(int[] initArr){
    if(initArr.length > 1){
        //记录最后一次交换的位置
        int lastExchangeIndex = 0;
        //内层循环的边界位置
        int sortBorder = initArr.length-1;
        for(int i =0; i < initArr.length; i++){
            boolean isSorted = true;
            for(int j =0; j < sortBorder; j++){
                if(initArr[j] > initArr[j+1]){
                    int temp = initArr[j];
                    initArr[j] = initArr[j+1];
                    initArr[j+1] = temp;
                    isSorted = false;
                    lastExchangeIndex = j;
                }
            }
            sortBorder = lastExchangeIndex;
            if(isSorted){
                break;
            }
        }
    }
    return initArr;
}

 

冒泡排序是单向冒泡的,双向冒泡的也有,叫做鸡尾酒冒泡。有时间再介绍。
posted @ 2019-12-03 11:37  akunkun  阅读(113)  评论(0)    收藏  举报