19*:排序算法2:选择排序(从未排序区间找最小元素,和排序区间的最后一个元素交换位置。)

问题

- (void)selectionAscendingOrderSortWithArray:(NSMutableArray *)ascendingArr
{
    int index = 0;//记录找到的关键字下标
    for (int i = 0; i < arr.count - 1; i++) {
      index = i;
      for (int j = i + 1; j < arr.count; j++) {
          if ([arr[index] integerValue] < [arr[j]integerValue]) {
            //如果有比当前index值大的值,则记录次下标
            index = j;//记录最大值(最小值)的下标
          }
      }
      if (i != index) {  //若index不等于i,说明找到最大值,交换
          [arr exchangeObjectAtIndex:i withObjectAtIndex:index];
      }
    NSLog(@"%@",arr);
}

目录

 

预备

 

正文

1:选择排序

1:算法描述

给定 N个项目和 L = 0的数组,选择排序将:

 

    1. 在 [L ... N-1]范围内找出最小项目 X的位置,
    2. 用第 L项交换X,
    3. 将下限 L增加1并重复步骤1直到 L = N-2

2:算法思想

选择排序分已排序区间和未排序区间,其实就是从头遍历,要排第几个元素,每次从剩余未排序元素里面找最小的元素,交换位置。

重复(元素个数-1)次

  把第一个没有排序过的元素设置为最小值

  遍历每个没有排序过的元素

    如果元素 < 现在的最小值

      将此元素设置成为新的最小值

  将最小值和第一个没有排序过的位置交换

3:动图演示

  •  红色表示当前遍历到的最小值
  • 黄色的条代表已经排好序的元素;

  • 绿色的代表此算法正在操作,进行比较交换的元素

  • 蓝色代表还没有排序的

4:代码实现

public class SelectSort {
    public static int[] selectSort(int[] a) {
        int n = a.length;
        // 从头开始遍历,选定某个元素待排序
        for (int i = 0; i < n - 1; i++) {
          // 将这个元素设为最小值
            int min = i;
            // 遍历所有未排过序的元素,从第i个元素右边开始
            for (int j = i + 1; j < n; j++) {
              // 如果元素小于当前最小值,那么最小值改为当前值
                if(a[min] > a[j]) 
                 min = j;
            }
            // 以上得到了当前最小值,将当前最小值提到前面
            //交换
            int temp = a[i];
            a[i] = a[j];
            a[j] = temp;
        }
        return a;
    }
}
  • 稳定性分析

    不稳定。从动画当中可以看出,选择排序每次都要找剩余未排序元素中的最小值,并和前面的元素交换位置,这样破坏了稳定性。

    如果你还是难以理解,那么举个栗子,比如4,6,4,2,7这样一组数据,使用选择排序算法来排序的话,第一次找到最小元素2,与第一个5交换位置,那第一个4和中间的4顺序就变了,所以就不稳定 了。正是因此,相对于冒泡排序和插入排序,选择排序就稍微逊色了。

  • 时间复杂度分析

    最好和最坏情况都是n的平方,因为每次都是去查寻最小的元素,第二层的遍历无论如何也要做,避免不了,因此选择排序可谓是弟中弟。

OC代码

原理:从第一个元素开始,依次查找对比,找到最小的元素与第一个元素交换,再从第二个元素开始找后面元素的最小值与第二个元素交换,以此类推,直到整个数组有序。

时间复杂度和空间复杂度与冒泡排序一样

- (void)selectionAscendingOrderSortWithArray:(NSMutableArray *)ascendingArr
{
    int index = 0;//记录找到的关键字下标
    for (int i = 0; i < arr.count - 1; i++) {
      index = i;
      for (int j = i + 1; j < arr.count; j++) {
          if ([arr[index] integerValue] < [arr[j]integerValue]) {
            //如果有比当前index值大的值,则记录次下标
            index = j;//记录最大值(最小值)的下标
          }
      }
      if (i != index) {  //若index不等于i,说明找到最大值,交换
          [arr exchangeObjectAtIndex:i withObjectAtIndex:index];
      }
    NSLog(@"%@",arr);
}

冒泡与选择对比:

选择比冒泡效率高,一次循环只交换一次,冒泡也可以记录坐标进行一次交换,但空间复杂度就增加,冒泡可以检验数组是否有序,如果循环中没有一次交换说明是有序的,可以提前终止

冒泡排序在内循环交换,选择排序在外循环交换,效率差也就在这个交换次数上,毕竟O(n)<O(n^2)。如果数组完全有序,冒泡内循环的交换一次都不会执行,而选择排序每次还要和本身交换一次,此时冒泡效率高。

注意

 

引用

1:极客算法训练笔记(五),十大经典排序之冒泡,选择,插入排序

2:iOS选择排序

3:OC-排序算法总结(冒泡、快速、插入、选择、希尔、堆)

posted on 2020-12-12 20:19  风zk  阅读(220)  评论(0编辑  收藏  举报

导航