算法 - 选择排序和冒泡排序

今天讲一下选择排序和冒泡排序,这是两种很简单的排序算法。

一、冒泡排序法(BubbleSort)

从数组的第一个元素开始,进行两两比较,较大的移到前面,较小的移到后面,经过一轮比较后,最大的数将会被移动到最后面。

最无脑版本:

public int[] bubbleSort(int[] arr){
    for(int i = 0; i < arr.length; i++){
            for(int j = 0;j < arr.length-1; j++){
                if(arr[j] > arr[j+1]){
                    int temp = arr[j+1];
                    arr[j+1] = arr[j];
                    arr[j] = temp;
                }
            }
            //打印数组,查看排序过程             /*for (int ii : arr) {  System.out.print(ii+"->");  }  System.out.println("\b\b");*/
    }
    return arr;
}

去掉注释代码,程序输出:

5->2->7->3->8->1->6->9

2->5->3->7->1->6->8->9

2->3->5->1->6->7->8->9

2->3->1->5->6->7->8->9

2->1->3->5->6->7->8->9

1->2->3->5->6->7->8->9

1->2->3->5->6->7->8->9

1->2->3->5->6->7->8->9

这个版本有两个大问题:

  1. 假设我们把每次内循环完成称为“一轮”,每一轮过后,数组arr的最后一位元素已经是最大的了,而我们还是把它进行了比较,所以内层循环的“上限”需要修改。
  2. 通过上面输出我们可以发现,最后三轮比较没有交换任何元素,也就是说已经排序完成,可是我们的程序还是在“傻傻的”运行,所以我们应该设置一个flag,当检测到数组排好序后,终止程序。

修改版:

public int[] bubbleSort(int[] arr){
    boolean swapNone;
    for(int i = 0; i < arr.length; i++){
            swapNone = true; //初始化flag             for(int j = 0;j < arr.length-1-i; j++){
                //这里注意是j < arr.length-1-i                 if(arr[j] > arr[j+1]){
                    int temp = arr[j+1];
                    arr[j+1] = arr[j];
                    arr[j] = temp;
                    swapNone = false;//记录交换                 }
            }
            //如果无交换,结束             if(swapNone)break;
            //打印数组,查看排序过程             /*for (int ii : arr) {  System.out.print(ii+"->");  }  System.out.println("\b\b");*/
    }
    return arr;
}

去掉注释代码,程序输出:

5->2->7->3->8->1->6->9

2->5->3->7->1->6->8->9

2->3->5->1->6->7->8->9

2->3->1->5->6->7->8->9

2->1->3->5->6->7->8->9

1->2->3->5->6->7->8->9

完美!

那么,冒泡排序的时间复杂度是O(n^2),空间复杂度是O(1)。

一般来说,冒泡排序是稳定的排序算法,但是如果比较条件中 arr[j]<arr[j+1]的“<”改为“<=”,那么冒泡排序就不稳定了。关于稳定性分析,我会在其他文章讲到。

二、选择排序法(SelectionSort

选择排序的思路,和人类的思维是很相似的:先找出最小的来,放在第一位;然后再找出第二小的,放到第二位;再找出第三小的,以此类推。

代码如下:

public int[] selectionSort(int[] arr){
        for(int i = 0; i < arr.length; i++){
            //第i轮查找,找出第i小的,放到第i位             int minIndex = i;
            //从i+1开始和第i个进行比较             for(int j = i+1; j < arr.length-1; j++){
                //n个数共需要比较n-1次,最大的数自动被“挤”到最后                 if(arr[j] < arr[minIndex]){
                    minIndex = j;
                }
            }
            if(minIndex != i){
                int temp = arr[minIndex];
                arr[minIndex] = arr[i];
                arr[i] = temp;
            }
            //打印数组,查看排序过程             /*for (int ii : arr) {  System.out.print(ii+"->");  }  System.out.println("\b\b");*/
        }
        return arr;
    }

去掉注释代码,程序输出:

1->5->2->7->3->8->9->6

1->2->5->7->3->8->9->6

1->2->3->7->5->8->9->6

1->2->3->5->7->8->9->6

1->2->3->5->6->8->9->7

1->2->3->5->6->7->9->8

1->2->3->5->6->7->8->9

完美!

那么,选择排序的时间复杂度是O(n^2),空间复杂度是O(1)。

稳定性不敢讲,有大佬知道的,可以在评论区告诉我。大家也可以自行百度~~~

    原文作者:李井瑞
    原文地址: https://zhuanlan.zhihu.com/p/34437881
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞