数据结构与算法-选择排序

164 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第12天,点击查看活动详情

前言

了解冒泡排序后接下来介绍一种新的排序算法:选择排序。通过选择排序来和冒泡排序作对比,比较一下两者排序效率如何以及各个优缺点。

选择排序

选择排序过程是在数组中找出最小值,然后一次从左到右做替换。

索引0索引1索引2索引3索引4索引5
253147
  1. 例如初始无序数组,首选一个待定索引以及一个指向索引0,当前就先待定索引赋值为索引0因为目前它是最小值。
索引0索引1索引2索引3索引4索引5
153247
  1. 接着指向索引索引1待定索引赋值比索引1要大(2 > 1),待定索引赋值为索引1
  2. 接着指向索引索引2,继续和待定索引赋值数进行比较...
  3. 直到轮回到最后,待定索引赋值是当前数组最小值了,将待定索引的数据填入索引0,并将原索引0的数据替换到最小值的索引。
  4. 后续过程如上执行直到待定索引指向索引5结束。

原理

冒泡排序比作相邻两个指针做比较的话,选择排序是一个指针指向数组,一个暂存下标来记录当前最小值。

253147

指针指向索引0起始暂存下标记录是0,然后指针指向索引1 = 5,比暂存下标值要大,继续往后查询...直到找到值为1的索引3暂存下标变成3,接着继续往后得到当前最小值是1且是索引3。然后索引0索引3数值交换。

image.png

以上过程结束后再进行下一步指针指向索引1始暂存下标记录是1,继续如上过程找出最小的值,然后索引1索引X数值交换。

算法代码

i表示数组循环次数,j表示当前指针指向。min作为当前最小值下标记录。

void main(){
    int min;
    int[] datas;
    for(int i=0;i<datas.length - 1;i++){
        min = i;
        for(int j= i + 1;j<datas.length;j++){
            if(datas[min] > datas[j]){
                min = j;
            }
        }
        if(min != i){
             int temp = datas[min];
             datas[min] = datas[i];
             datas[i] = temp;
        }
    }
}

假设N个数据执行以上算法 (N1+(N2)+(N3)...+1(N-1)+ (N-2)+ (N-3)... +1可推导出大O记法为O(N2N^2)。 选择排序在此过程中每次循环最坏情况交换次数只有一次,而冒泡排序每次循环最坏情况每次都需要进行一次排序。从实际数据统计上看选择排序效率会比冒泡排序快上一倍。

大O忽略常数

因此选择排序最优情况下大O记法为O(N2/2N^2/2),但实际情况选择排序和冒泡排序一样记作O(N2N^2)。

  • 大O记法一般不包含数字(指数等其他情况例外),比如O(2N2*N)记作O(NN),O(200N200*N)也会被记作O(NN)。
  • 当在大数据情况下以上可以这么考虑忽略,但实际情况下当然快100倍200倍的算法当然是选择更快的。
  • 存在临界点的原因大O记法会忽略常数,大O不关心临界点位置它只表明在总体情况下一类算法会比一类算法快。