# 冒泡排序

> 我想对于它每个学过C语言的都会了解，这可能是很多人接触的第一个排序算法。

* 基本思想

  冒泡排序（Bubble Sort）是一种简单的排序算法。它重复地走访过要排序的数列，一次比较两个元素，如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换，也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。

  <img src="https://i.loli.net/2017/10/20/59e9e6dec6984.gif" alt="bubble.gif" data-size="original">
* 算法描述
  1. 比较相邻的元素，如果第一个比第二个大，就交换他们两个。
  2. 对每一对相邻元素作同样的工作，从开始第一对到结尾的最后一对。这步做完后，最后的元素会是最大的数。
  3. 针对所有的元素重复以上的步骤，除了最后一个。
  4. 持续每次对越来越少的元素重复上面的步骤①\~③，直到没有任何一对数字需要比较。
* 代码实现

  冒泡排序需要两个嵌套的循环. 其中, 外层循环移动游标; 内层循环遍历游标及之后(或之前)的元素, 通过两两交换的方式, 每次只确保该内循环结束位置排序正确, 然后内层循环周期结束, 交由外层循环往后(或前)移动游标, 随即开始下一轮内层循环, 以此类推, 直至循环结束。

  ```java
  /**
   * 冒泡排序
   * <p>
   * 1. 比较相邻的元素。如果第一个比第二个大，就交换他们两个。
   * 2. 对每一对相邻元素作同样的工作，从开始第一对到结尾的最后一对。这步做完后，最后的元素会是最大的数。
   * 3. 针对所有的元素重复以上的步骤，除了最后一个。
   * 4. 持续每次对越来越少的元素重复上面的步骤①~③，直到没有任何一对数字需要比较。
   *
   * @param arr 待排序数组
   */
  public static void bubbleSort(int[] arr) {
      for (int i = arr.length - 1; i > 0; i--) {  //外层循环移动游标
          for (int j = 0; j < i; j++) {    //内层循环遍历游标及之后(或之前)的元素
              if (arr[j] > arr[j + 1]) {
                  int temp = arr[j];
                  arr[j] = arr[j + 1];
                  arr[j + 1] = temp;
              }
          }
          System.out.println("Sorting: " + Arrays.toString(arr));
      }
  }
  ```
* 小结

  冒泡排序算法复杂度:

  | 平均时间复杂度 | 最好情况 | 最坏情况  | 空间复杂度 |
  | ------- | ---- | ----- | ----- |
  | O(n²)   | O(n) | O(n²) | O(1)  |

  * 若文件初状为正序，则一趟起泡就可完成排序，排序码的比较次数为`n-1`，且没有记录移动，时间复杂度是`O(n)`

  * 若文件初态为逆序，则需要`n-1`趟起泡，每趟进行`n-i`次排序码的比较，且每次比较都移动三次，比较和移动次数均达到最大值 `O(n2)`

  * 起泡排序平均时间复杂度为`O(n2)`

  > 注意：由于冒泡排序只在相邻元素大小不符合要求时才调换他们的位置，它并不改变相同元素之间的相对顺序，因此它是稳定的排序算法
