算法基础——冒泡排序

冒泡排序的基本思想

冒泡排序是一种交换排序,它的基本思想是:相邻的两两元素互相比较,如果是反序则位置交换,直到没有反序为止。举一个比较通俗的例子:小时候我们都经历过高矮个排队,如果在排队的过程中我们使用冒泡排序的话,首先第一个同学会与他右边的同学比较身高,如果比右边高的话则两个人互换顺序,矮的话则保持不动,之后第二个位置的同学与他右边的同学比较,如此重复,如果有N个同学的话则第一趟排序需要进行N-1次比较,第一趟排序完成之后身高最高的同学会站在最右边,我们来画一张简单的示意图:


排序之前的队伍

这是排序之前的队伍,首先先进行第一次的排序:
(1)一号位跟二号位比较,一号位比二号位高,双方互换位置。
(2)二号位与三号位比较,二号位比三号位高,双方互换位置。
(3)三号位与四号位比较,三号位比四号位高,双方互换位置。
这样就完成了第一次的排序,最高的会在最右边的四号位,如下图所示。
这里写图片描述

然后进行第二次排序:
(1)一号位跟二号位比较,一号位比二号位低,位置不变。
(2)二号位与三号位比较,二号位比三号位高,双方互换位置。
由于第一次排序中四号位已经是最高的了,所以三号位无需再与四号位进行比较。这样就完成了第二次的排序,具体顺序如下图所示。
这里写图片描述

最后我们进行第三次排序:这次排序只剩下一号位与二号位比较,因为前两次的排序中已经确定了三号位跟四号位的位置,一号位与二号位相比,一号位比二号位高,双方互换位置,于是我们就完成了整个排序,具体顺序如下图:
这里写图片描述

接着我们用Java代码来描述一下排序过程:

public class BubbleTest {
    public static void main(String[] args) {
        int[] data = new int[]{15, 20, 2, 17};
        bubbleSort(data);
        for (int i : data) {
            System.out.println(i);
        }
    }

    public static void bubbleSort(int[] data) {
        int length = data.length;
        //对于N个元素,只需要进行N-1次排序
        for (int i = 0; i < length - 1; i++) {
            for (int j = 0; j < length - i - 1; j++) {
            //相邻两元素比较,如果反序,则互换位置
                if (data[j] > data[j + 1]) {
                    swap(data, j, j + 1);
                }
            }
        }
    }

    public static void swap(int[] data, int from, int to) {
        int temp = data[from];
        data[from] = data[to];
        data[to] = temp;
    }
}

冒泡排序的优化

试想这样一种场景,对N个元素排序需要进行N-1次排序,如果我在前几次(小于N-1)就已经得到了正确的序列,那么剩下的几次排序还有必要进行么?答案当然是No!具体效果如下图所示:
这里写图片描述

上述序列经过第一次排序:只有三号位与四号位位置互换,第一次排序完成之后就得到了正确的序列,剩下的第二次、第三次排序完全没有必要,如下图所示:
这里写图片描述

所以需要对我们之前的冒泡排序进行优化,怎么样才能知道我的序列已经是有序了呢?我们想:如果我在一次排序的过程中没有发生元素的位置呼唤,就说明序列本身就已经有序了。既然这样的话,那我们来优化一下我们的代码:

public class BubbleTest {
    public static void main(String[] args) {
        int[] data = new int[]{1, 2, 4, 3};
        bubbleSort(data);
        for (int i : data) {
            System.out.println(i);
        }
    }

    public static void bubbleSort(int[] data) {
        boolean isSwap = true;//序列是否进行过互换操作标识
        int length = data.length;
        //只有在标识为True的情况下才会进行排序
            for (int i = 0; i < length - 1&&isSwap; i++) {
                isSwap=false;
                for (int j = 0; j < length - i - 1; j++) {
                    if (data[j] > data[j + 1]) {
                        isSwap = swap(data, j, j + 1);
                    }
                }
            }
    }

    public static boolean swap(int[] data, int from, int to) {
        int temp = data[from];
        data[from] = data[to];
        data[to] = temp;
        return true;
    }
}

这样的话就省去了不必要的排序。

猜你喜欢

转载自blog.csdn.net/ww55555577/article/details/55102126
今日推荐