vlambda博客
学习文章列表

十大经典排序--选择排序及其优化

选择排序思路:


  • 首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置

  • 再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。

  • 重复第二步,直到所有元素均排序完毕。


为什么叫选择排序?

  • 因为它在不断地选择剩余元素之中的最小(大)者。


选择排序的特点:

  • 运行时间和输入无关。为了找出最小的元素而扫描一遍数组并不能为下一遍扫描提供什么信息;

  • 数据移动是最小的。每次交换都会改变两个数组元素的值,因此选择排序用了 N 次交换——交换次数和数组的大小是线性关系。(其他大部分排序算法的增长数量级都是线性对数或是平方级别的)


代码:

 1public void sort(int[] arr) {
2    int length = arr.length;//数组长度
3    for (int indexI = 0; indexI < length; indexI++) {
4        // 将arr[indexI]和arr[indexI+1...length]中最小的元素交换
5        int min = indexI;    // 最小元素的索引
6        for (int indexJ = indexI + 1; indexJ < length; indexJ++) {
7            if (arr[indexJ] < arr[min]) {
8                min = indexJ;
9            }
10        }
11        exch(arr, indexI, min);
12    }
13}
14private void exch(int[] arr, int i, int j) {
15    int temp = arr[i];
16    arr[i] = arr[j];
17    arr[j] = temp;
18}

时间复杂度:O(n2)

空间复杂度:O(1)


优化:

思路:上面代码的主要思路是,每次遍历剩余元素,找出其中最小值,只排定最小值。我们可以在每次遍历剩余元素的时候,同时找出其中最小值和最大值,并排定最小值和最大值。这样遍历的次数会减少一半。时间复杂度是O(N/2 * N /2),还是平方级别的。但是运行时间有了相应的减少。


代码:

 1public void sortPlus(int[] arr) {
2    for (int left = 0, right = arr.length - 1; left < right; left++, right--) {
3        int min = left;        // 记录最小值
4        int max = right;     // 记录最大值
5        for (int index = left; index <= right; index++) {
6            if (arr[index] < arr[min]) {
7                min = index;
8            }
9            if (arr[max] < arr[index]) {
10                max = index;
11            }
12        }
13        // 将最小值交换到 left 的位置
14        exch(arr, left, min);
15        //注意 由于咱们是先排最小值的位置,交换过后left位置的数据会发生变化
16        //所以得考虑最大值(arr[max])在最小位置(left)的情况。
17        if (left == max) {
18            max = min;
19        }
20        exch(arr, right, max);
21    }
22}
23private void exch(int[] arr, int i, int j) {
24    int temp = arr[i];
25    arr[i] = arr[j];
26    arr[j] = temp;
27}

时间复杂度:O(n/2 * n/2)

空间复杂度:O(1)


以上仅是个人思路解法,觉得还不错欢迎点赞关注分享


往期精彩推荐