冒泡排序思路实现及优化

        冒泡排序是排序算法中,容易理解且简单的一种算法

主要思路如下:

  1. 依次比较数组中相邻两个元素大小,若 a[j] > a[j+1],则交换两个元素,两两都比较一遍称为一轮冒泡,结果是让最大的元素排至最后

  2. 重复以上步骤,直到整个数组有序

1.基本实现

        在每一轮遍历中,相邻两个数据进行比较,当左边比右边大时,两者交换位置。每一轮完成后,都会有一个最大的值放在最后。循环结束后数组即排序完成。

public static void bubble(int[] a) {

        for (int j = 0; j < a.length - 1; j++) {

            // 一轮冒泡
            for (int i = 0; i < a.length - 1; i++) {
                System.out.println("比较次数" + i);
                if (a[i] > a[i + 1]) {
                    //交换位置
                    Utils.swap(a, i, i + 1);
                    swapped = true;
                }
            }

            System.out.println("第" + j + "轮冒泡"
                    + Arrays.toString(a));
    
        }
    }

2.优化1

        在内层循环中我们发现,循环的次数是从头遍历比较到尾,但是其实在前面的循环中,我们数组后边的数据其实是已经排好序了。比如我们在第一次循环中,会将数组中的最大的数放在数组最后一个位置。在第二次循环中,将数组中第二大的数放在倒数第二个位置。以此类推,其实数组末尾的数随着循环排序的进行,是已经有序的,所以末尾的数据比较是没有必要的。

        所以修改内层循环的循环次数

public static void bubble(int[] a) {

        for (int j = 0; j < a.length - 1; j++) {

            // 一轮冒泡            //优化比较次数
            for (int i = 0; i < a.length - 1 - j; i++) {
                System.out.println("比较次数" + i);
                if (a[i] > a[i + 1]) {
                    //交换位置
                    Utils.swap(a, i, i + 1);
                    swapped = true;
                }
            }

            System.out.println("第" + j + "轮冒泡"
                    + Arrays.toString(a));
    
        }
    }

3.优化2

       在某些情况下,其实我们的数组,在总体循环完成之前,就已经有序了。所以在有序之后的操作其实是没必要的。我们可以优化这里的代码。设置一个标志位,检查一轮循环中是否发生了交换,如果没有即数组有序。

public static void bubble(int[] a) {
        for (int j = 0; j < a.length - 1; j++) {
            // 一轮冒泡
            boolean swapped = false; // 是否发生了交换
            for (int i = 0; i < a.length - 1 - j; i++) {
                System.out.println("比较次数" + i);
                if (a[i] > a[i + 1]) {
                    Utils.swap(a, i, i + 1);
                    swapped = true;
                }
            }
            System.out.println("第" + j + "轮冒泡"
                    + Arrays.toString(a));
            if (!swapped) {
                break;
            }
        }
    }

4.最终优化(拓展

        通过记录每一轮循环,最后发生交换的位置,减少下一轮比较的个数(在特殊情况下有用,一般使用优化2版就可以了,可以当作拓展

public static void bubble_v2(int[] a) {
        int n = a.length - 1;
        while (true) {
            int last = 0; // 表示最后一次交换索引位置
            for (int i = 0; i < n; i++) {
                System.out.println("比较次数" + i);
                if (a[i] > a[i + 1]) {
                    Utils.swap(a, i, i + 1);
                    last = i;
                }
            }
            n = last;
            System.out.println("第轮冒泡"
                    + Arrays.toString(a));
            if (n == 0) {
                break;
            }
        }
    }

你可能感兴趣的:(algorithm,算法,数据结构)