排序算法之--冒泡排序

438 阅读3分钟

冒泡排序及优化

冒泡排序算法的原理如下

  • 1.比较相邻的元素。如果第一个比第二个大,就交换他们两个.
  • 2.对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
  • 3.针对所有的元素重复以上的步骤,除了最后一个。
  • 4.持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

针对步骤一,二:代码如下,遍历整个数组第一轮比较将最大的数下沉到最底部

         //3 1 5 8 2 9 4 6 7-->1 3 5 2 8 4 6 7 9
 	//比较,筛选出当前列最大的数放到最后
            for (int j = 1; j < array.length; j++) {
                if (array[j] > data[j + 1]) {
                    int temp = array[j];
                    array[j] = array[j + 1];
                    array[j + 1] = temp;
                }
            }

针对步骤三,四代码如下: 从第一位到倒数第二位置:做一次步骤一,二的两两比较排序:

 	//从后面逐步减少遍历个数
        for (int i = array.length-1; end > 0; i--) {
            步骤一
        }

所以:冒泡排序的总体算法如下

   public static void bubbleSort(int[] array){
        //3 1 5 8 2 9 4 6 7    n*(n-1)/2    n
      //第一轮比较结果:1 3 5 2 8 4 6 7 9 数字最大的沉到最低
        for(int i=array.length-1;i>0;i--) {
            for (int j = 0; j < i; j++) {
                if (array[j] > array[j + 1]) {
                    int temp = array[j];
                    array[j] = array[j + 1];
                    array[j + 1] = temp;
                    flag=false;
                }
            }
        }
    }

总体运行如下:

    @Test
    public void testSort(){
        int[] array=new int[]{3,2,5,8,1,9,4,6,7};
        for (int i : array) {
            System.out.print(i+" ");
        }
        System.out.println("\n");
        bubbleSort(array);
        for (int i : array) {
            System.out.print(i+" ");
        }

    }
    public static void bubbleSort(int[] array){
        //3 1 5 8 2 9 4 6 7    n*(n-1)/2    n
      //第一轮比较结果:1 3 5 2 8 4 6 7 9 数字最大的沉到最低
        for(int i=array.length-1;i>0;i--) {
            for (int j = 0; j < i; j++) {
                if (array[j] > array[j + 1]) {
                    int temp = array[j];
                    array[j] = array[j + 1];
                    array[j + 1] = temp;
                    flag=false;
                }
            }
        }
    }

运行结果如下:

image.png

冒泡排序的时间复杂度是:O(n^2)。

优化一

如果swap一次都没执行,说明当前元素已经是有序的了

   public static void bubbleSort(int[] array){
        //3 1 5 8 2 9 4 6 7    n*(n-1)/2    n
      //第一轮比较结果:1 3 5 2 8 4 6 7 9 数字最大的沉到最低
        for(int i=array.length-1;i>0;i--) {
            boolean flag=true;
            for (int j = 0; j < i; j++) {
                if (array[j] > array[j + 1]) {
                    int temp = array[j];
                    array[j] = array[j + 1];
                    array[j + 1] = temp;
                    flag=false;
                }
            }
            if(flag){
                break;
            }
        }
    }

优化二

可以记录最后一次交换的位置,最后一次交换位置后续的元素就是有序的。 比如说: 3,4,1,5,7,10其中最后一次是1的位置,他后面的位置就是有序的,没有必要再比较了。 所以下一轮再进来的时候只需要将前面无序的再扫描一遍就行:

private static void sort3(int[] array) {
        //从后面逐步减少遍历个数
        for (int end = array.length - 1; end > 0; end--) {
            //sortIndex最后会复制给end,
            //sortIndex需要考虑完全有序的时候,end会就是初始值,
            //此时要退出循环,所以可以设置1,0等让下次循环条件不符合。
            int sortIndex = 0;
            //比较,筛选出当前列最大的数放到最后
            for (int start = 1; start <= end; start++) {
                if (array[start] <array[start - 1]) {
                    swap(array,start,start-1);
                    //记录最后一次交换的位置
                    sortIndex = start;
                }
            }
            //缩小下一轮扫描范围
            end = sortIndex;

        }
    }

    private static void swap(int[] data, int first, int end) {
        int temp = data[first];
        data[first] = data[end];
        data[end] = temp;
    }

运行:

   @Test
    public void testSort() {
//        int[] array=new int[]{3,2,5,8,1,9,4,6,7};
        int[] array = new int[]{3, 4, 1, 5, 7, 10};
        for (int i : array) {
            System.out.print(i + " ");
        }
        System.out.println("\n");
        sort3(array);
        for (int i : array) {
            System.out.print(i + " ");
        }

    }

结果:

image.png