【Data Structure/Algorithm】排序之冒泡排序

来源:互联网 发布:软件行业目标市场分析 编辑:程序博客网 时间:2024/04/30 03:18

排序算法中最入门的一个排序算法就是冒泡排序,面试中经常会考到的一个基础题目。那么什么是冒泡排序呢?以及冒泡排序算法的基本原理是什么呢?
本文会一 一解答。

1,冒泡排序及其原理

原理:比较两个相邻的元素,将值大的元素交换至右端。

思路:第一趟,依次比较相邻的两个数,将小数放在前面,大数放在后面。重复第一趟步骤,每次从数组的第一个元素从头开始,直至全部排序完成。

2,示例

(本示例摘自http://www.cnblogs.com/shen-hua/p/5422676.html)
举例说明:要排序数组:int[] arr={6,3,8,2,9,1};

第一趟排序:

    第一次排序:6和3比较,6大于3,交换位置: 3 6 8 2 9 1

    第二次排序:6和8比较,6小于8,不交换位置:3 6 8 2 9 1

    第三次排序:8和2比较,8大于2,交换位置: 3 6 2 8 9 1

    第四次排序:8和9比较,8小于9,不交换位置:3 6 2 8 9 1

    第五次排序:9和1比较:9大于1,交换位置: 3 6 2 8 1 9

    第一趟总共进行了5次比较, 排序结果: 3 6 2 8 1 9


第二趟排序:

    第一次排序:3和6比较,3小于6,不交换位置:3 6 2 8 1 9

    第二次排序:6和2比较,6大于2,交换位置: 3 2 6 8 1 9

    第三次排序:6和8比较,6大于8,不交换位置:3 2 6 8 1 9

    第四次排序:8和1比较,8大于1,交换位置: 3 2 6 1 8 9

    第二趟总共进行了4次比较, 排序结果: 3 2 6 1 8 9


第三趟排序:

    第一次排序:3和2比较,3大于2,交换位置: 2 3 6 1 8 9

    第二次排序:3和6比较,3小于6,不交换位置:2 3 6 1 8 9

    第三次排序:6和1比较,6大于1,交换位置: 2 3 1 6 8 9

    第二趟总共进行了3次比较, 排序结果: 2 3 1 6 8 9


第四趟排序:

    第一次排序:2和3比较,2小于3,不交换位置:2 3 1 6 8 9

    第二次排序:3和1比较,3大于1,交换位置: 2 1 3 6 8 9

    第二趟总共进行了2次比较, 排序结果: 2 1 3 6 8 9


第五趟排序:

    第一次排序:2和1比较,2大于1,交换位置: 1 2 3 6 8 9

    第二趟总共进行了1次比较, 排序结果: 1 2 3 6 8 9


最终结果:1 2 3 6 8 9

冒泡排序的优点:每进行一趟排序,就会少比较一次,因为每进行一趟排序都会找出一个较大值。如上例:第一趟比较之后,排在最后的一个数一定是最大的一个数,第二趟排序的时候,只需要比较除了最后一个数以外的其他的数,同样也能找出一个最大的数排在参与第二趟比较的数后面,第三趟比较的时候,只需要比较除了最后两个数以外的其他的数,以此类推……也就是说,每进行一趟比较,每一趟少比较一次,一定程度上减少了算法的量。

3,实现代码

Bubble.java

package sort;public class Bubble {    public static void main(String[] args) {        int[] a={2,1,5,3,8,2,0};//      sort1(a);//      sort2(a);        sort3(a);        for(int i:a){            System.out.println(i);        }    }    /**     * 没有做任何优化的算法     * 外层循环为一共需要多少趟排序,内层循环为每一趟需要多少次排序     * @param a     */    public static void sort1(int[] a){        int length=a.length;        for(int i=0;i<length-1;i++){            for(int j=0;j<length-i-1;j++){                if(a[j]>a[j+1]){                    int temp=a[j];                    a[j]=a[j+1];                    a[j+1]=temp;                }            }        }    }    /**     * 优化的排序算法     * 优化的地方有两点:     *  1,每趟排序之后,最后一个数字一定是最大值     *  2,根据这一趟是否有数值交换就可以判断是否已经排序完毕     * @param a     */    public static void sort2(int[] a){        boolean changed=true;        int num=a.length-1;        while(changed){            changed=false;            for(int i=0;i<num;i++){                if(a[i]>a[i+1]){                    int temp=a[i];                    a[i]=a[i+1];                    a[i+1]=temp;                    changed=true;                }            }            num--;        }    }    /**     * 优化的排序算法     * 这种冒泡算法的优势在于处理的数组满足下面的情况:     * 数组后一部分可能大于前一部分,因此后部分不需要进行排序     * 优化的地方有两点:     *  1,每趟排序之后,记录最后的交换位置,下次排序的范围就在这个标记的位置之前     *  2,每趟排序都要将flag置零,排序的终止条件就是flag=0的时候     *      * @param a     */    public static void sort3(int[] a){        int num=a.length-1;        int flag=num;        while(flag>0){            int k=flag;            flag=0;            for(int i=0;i<k;i++){                if(a[i]>a[i+1]){                    int temp=a[i];                    a[i]=a[i+1];                    a[i+1]=temp;                    flag=i;                }            }        }    }}

结论:
1,第一种排序算法,冒泡排序法的时间复杂度O(N^2),因为每一趟都要进行比较
2,第二种排序算法和第三种算法,冒泡排序法的时间复杂度取决于输入的数组。最优时间复杂度为O(N),最坏时间复杂度为O(N^2)。