> For the complete documentation index, see [llms.txt](https://bing.gitbook.io/phper/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://bing.gitbook.io/phper/data/algorithm/pai-xu/xuan-ze-pai-xu.md).

# 选择排序

* 基本思想

  选择排序的基本思想：比较 + 交换。

  在未排序序列中找到最小（大）元素，存放到未排序序列的起始位置。在所有的完全依靠交换去移动元素的排序方法中，选择排序属于非常好的一种。

  <img src="https://i.loli.net/2017/10/21/59ea1f75af23e.gif" alt="selection.gif" data-size="original">
* 算法描述
  1. 从待排序序列中，找到关键字最小的元素；
  2. 如果最小元素不是待排序序列的第一个元素，将其和第一个元素互换；
  3. 从余下的 N - 1 个元素中，找出关键字最小的元素，重复1、2步，直到排序结束。
* 代码实现

  选择排序比较简单，以下是我自己的实现，跟官方版差不多，所以完全可以参考。

  ```java
  /**
   * 选择排序
   *
   * 1. 从待排序序列中，找到关键字最小的元素；
   * 2. 如果最小元素不是待排序序列的第一个元素，将其和第一个元素互换；
   * 3. 从余下的 N - 1 个元素中，找出关键字最小的元素，重复1、2步，直到排序结束。
   *    仅增量因子为1 时，整个序列作为一个表来处理，表长度即为整个序列的长度。
   * @param arr  待排序数组
   */
  public static void selectionSort(int[] arr){
      for(int i = 0; i < arr.length - 1; i++){
          int min = i;
          for(int j = i+1; j < arr.length; j++){    //选出之后待排序中值最小的位置
              if(arr[j] < arr[min]){
                  min = j;
              }
          }
          if(min != i){
              int temp = arr[min];      //交换操作
              arr[min] = arr[i];
              arr[i] = temp;
              System.out.println("Sorting:  " + Arrays.toString(arr));
          }
      }
  }
  ```
* 小结

  以下是选择排序复杂度:

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

  选择排序的简单和直观名副其实，这也造就了它”出了名的慢性子”，无论是哪种情况，哪怕原数组已排序完成，它也将花费将近 `n²/2` 次遍历来确认一遍。其实选择排序可以看成冒泡排序的优化，因为其目的相同，只是选择排序只有在确定了最小数的前提下才进行交换，大大减少了交换的次数。

  所以结论是选择排序和冒泡排序一样，都是 `O(n²)` 的效率，但选择排序无疑更快，因为它交换的次数更少。

  > 注意：选择排序是不稳定的排序
