当前位置:编程学习 > JAVA >>

冒泡排序

冒泡排序法<详解+优化>
冒泡排序法,是个大学生都听过吧,游泳时也会吹个泡泡什么的,这个排序算法被老师作为排序算法的入门算法,很基础,由于名字比较特别,我就一直记住了,今天想把这个写下来。
 
冒泡思想:
假如将不同的数放在不同的气泡中,依次是最小的数放在最大的气泡中,那么,我们知道,在水中,这些气泡会上浮,越大越容易上浮,那么,当一连串气泡挨在一起时,两个相邻的气泡就会在浮力东风作用下交换位置,浮力大的,也就是大的气泡上浮,就这样,一次交换下去,最后是最大的气泡在最上面。
 
冒泡排序:
Bubble sort 属于一种交换排序,两两比较相邻记录的关键字,如果反序则交换,直到没有反序的记录为止。
 
两两比较:
@反序:两两交换。
@正序:指针后移,下两个记录两两比较。
 
看一个冒泡排序一轮排序的的过程:
 
也就是两两比较,以数组为例,比较过程:
第一轮:数组下标为0的元素与1的元素相比,25<36,正序,指针后移,36>21反序,交换36和21,指针后移,36<45正序,指针后移,45<98正序,指针后移,98>13反序,交换98和13,最后98位于为底端,也就是数组的末尾。比较次数为(n-1)
第二轮:还是从数组下标为0开始两两比较,在第一比较后的结果98就不参与比较,比较次数为(n-2);
......
核心比较和交换的代码:
[java]  
/** 
     * 原始的冒泡排序法,时间复杂度为O(n2) 
     *  
     * @param array 
     */  
    public void bubbleSort(int... array) {  
        int length = array.length;  
        for (int i = 0; i < length - 1; i++) {  
            for (int j = 0; j < length - i - 1; j++) {// 内部循环的边界要比长度小一  
                if (array[j] > array[j + 1]) {  
                    swap(j, j + 1, array);//相邻的两个元素比较,将大的放到最右边  
                }  
            }  
        }  
    }  
@注意上边的外部循环的边界是 length-1,因为最后一个元素不用比较了。
[java]  
for (int i = 0; i < length - 1; i++)  
@内部循环的边界随着外部循环的变化而变化,也就是在前面比较后的记录就不用参与下一轮的比较。
[java] view plaincopy
for (int j = 0; j < length - i - 1; j++)  
@swap依然是一个交换数组两个元素的函数:
[java]  
/** 
     * 内部实现,用于交换数组的两个引用值 
     *  
     * @param beforeIndex 
     * @param afterIndex 
     * @param arr 
     */  
    private void swap(int oneIndex, int anotherIndex, int[] array) {  
        int temp = array[oneIndex];  
        array[oneIndex] = array[anotherIndex];  
        array[anotherIndex] = temp;  
    }  
 
那么将完整的代码列出来:
[java] 
/** 
 * 冒泡排序法 
 *  
 * @author PingCX 
 *  
 */  
public class BubbleSort {  
  
    public static void main(String[] args) {  
        BubbleSort bubbleSort = new BubbleSort();  
        int[] array = { 25, 36, 21, 45, 98, 13};  
        System.out.println(Arrays.toString(array));  
        bubbleSort.bubbleSort(array);// 调用快速排序的方法  
        System.out.println(Arrays.toString(array));// 打印排序后的数组元素  
    }  
  
    /** 
     * 原始的冒泡排序法,时间复杂度为O(n2) 
     *  
     * @param array 
     */  
    public void bubbleSort(int... array) {  
        int length = array.length;  
        for (int i = 0; i < length - 1; i++) {  
            for (int j = 0; j < length - i - 1; j++) {// 内部循环的边界要比长度小一  
                if (array[j] > array[j + 1]) {  
                    swap(j, j + 1, array);//相邻的两个元素比较,将大的放到最右边  
                }  
            }  
        }  
    }  
  
    /** 
     * 内部实现,用于交换数组的两个引用值 
     *  
     * @param beforeIndex 
     * @param afterIndex 
     * @param arr 
     */  
    private void swap(int oneIndex, int anotherIndex, int[] array) {  
        int temp = array[oneIndex];  
        array[oneIndex] = array[anotherIndex];  
        array[anotherIndex] = temp;  
    }  
}  
 
 
小结:冒泡排序法最核心的地方就是两两比较交换了,这种排序法容易被人理解和记忆,实现起来不难,性能稍高于比较排序算法,时间复杂度也是O(n²)
 
有一个问题来了:就是如果一个数组开始是有序的,照上面的算法,每一次都要进行比较,这样对有序的数组来说是多余的,我们是不是可以做一些改进,在第一轮比较之后,如果发现有序的,就是没有数据交换,后面的比较可以省去,直接跳出循环呢?
----->答案是可以的,这是我们需要一个标记,boolean  flag = true;辅助我们,看看下面的代码:
[java]  
/** 
     * 优化的冒泡排序法,时间复杂度为O(n2) 
     *  
     * @param array 
     */  
    public void bubbleSort(int... array) {  
        int length = array.length;  
        boolean flag = true; //一个标记  
        for (int i = 0; i < length - 1 && flag; i++) {//加这个条件就是当有序的时候就不用重复后面的操作了  
            flag = false;  
            for (int j = 0; j < length - i - 1; j++) {  
                if (array[j] > array[j + 1]) {  
                    swap(j, j + 1, array);// 相邻的两个元素比较,将大的放到最右边 &nb
补充:软件开发 , Java ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,