《算法笔记》笔记之笔记 - 4、算法初步(1) - 2.简单选择排序

16 篇文章 0 订阅
16 篇文章 0 订阅

4.1.2 简单选择排序

简单选择排序是最常用的选择类排序算法。对一个拥有 n n n个元素的序列,简单选择排序会进行n-1​趟操作,每一趟操作选出当前无序序列中最小(或最大)的元素,然后将其与无序序列的第一个(或最后一个)元素进行交换,这样最小(或最大)的元素就准确到位。

这么说可能有些抽象,我们来看一个小例子:从小到大排序{49, 38, 68, 97, 76, 13, 27, 49}。当前情况下,整个序列都是无序的。

无序
4938689776132749
  1. 第一趟

简单选择排序算法会遍历整个无序序列,通过比较,找出最小的元素在序列中的位置。然后,将最小的元素和无序序列中的第一个元素进行位置调换。这里13是最小的元素,第一趟操作之后被排在了它应该在的位置,可以说它现在是有序的了。

有序无序
1338689776492749
  1. 第二趟

之后,仍然遍历整个无序序列,找到当前的最小元素27,将其与无序序列的第一个元素进行位置调换。{13, 27}现在有序。

有序无序
1327689776493849

以此类推,我们一共会进行7趟操作,因为最后一个元素不需要再进行多余的比较,已经在它该在的位置上了,可以直接将它添加到有序中。所以对于简单选择排序算法而言,n个元素的无序序列要进行n-1趟操作。代码如下:

#include <cstdio>

int main(){

    int a[10] = {49, 38, 68, 97, 76, 13, 27, 49};

    // 记录每一趟无序序列中最小元素的位置
    int k;

    // 核心代码,进行n-1趟操作
    // 这里的8是序列元素个数,也就是上面的n,这么写方便理解
    // 顺便说一句,即使这里写成i<8也是可以的,也就是常说的n趟操作
    // 因为进行第n趟操作时,内层循环设定的初始是i+1,会根据条件自动跳出循环
    // 所以其实第n趟操作没有进行比较,且自己跟自己进行了个交换,感觉这样没必要
    for(int i=0; i<8-1; i++){
        // 存储无序序列中的第一个元素位置
        k = i;

        // 关键代码,找出无序序列中最小的元素
        // 从无序序列中的第二个元素开始
        for(int j=i+1; j<8; j++){
            if(a[j] < a[k]){
                k = j;
            }
        }

        // 将无序序列中的最小元素与无序序列中的第一个元素进行交换
        int temp = a[k];
        a[k] = a[i];
        a[i] = temp;
    }

    // 输出排列好的序列
    for(int i=0; i<8; i++){
        printf("%d", a[i]);
        if(i<8-1){
            printf(" ");
        }
    }
    printf("\n");

    return 0;
}

时间复杂度:将主要代码内层循环中的比较操作看作基本操作,考虑最坏情况。算法第一趟操作进行了n-1次比较,第二趟进行了n-2次比较,以此类推,第n-1趟操作进行了1次比较。于是总的操作次数为 ( 1 + ( n − 1 ) ) ∗ ( n − 1 ) 2 = n 2 − n 2 \frac{(1+(n-1))*(n-1)}{2} = \frac{n^2-n}{2} 2(1+(n1))(n1)=2n2n,简单选择排序的时间复杂度为 O ( n 2 ) O(n^2) O(n2)

空间复杂度:算法所需的辅助存储空间不随规模 n n n的变化而变化,是个常量,所以简单选择排序的空间复杂度为 O ( 1 ) O(1) O(1)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值