排序算法选择排序

Posted 程序员思语

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了排序算法选择排序相关的知识,希望对你有一定的参考价值。

在做前端工作的时候常常会对数组做处理,也经常会用到排序,今天开始将对常用排序算法做总结,顺便复习一些数据结构知识。
友情提示:阅读本文大概需要 10分钟

前言

选择排序,首先,找到数组中最小的那个元素,其次,将它和数组的第一个元素交换位置(如果第一个元素就是最小元素那么它就和自己交换)。再次,在剩下的元素中找到最小的元素,将它与数组的第二个元素交换位置。如此往复,直到将整个数组排序。之所以叫做选择排序,因为它在不断地选择剩余元素之中的最小者。

选择排序的内循环只是在比较当前元素与目前已知的最小元素(以及将当前索引 +1 和检查是否代码越界),这已经简单到了极点。交换元素的代码写在内循环之外,每次交换都能排定一个元素,因此交换的总次数是 N。所以算法的时间效率取决于比较的次数。

选择排序

题目背景
// 栗子
var array = [572891]

像任何其他排序一样,选择排序可以按照升序或降序的方式修改排序。按升序排序的方法如下:数组中最小的值被定位并移动到 数组array[0],然后定位下一个最小值并移动到 array[1],这个过程一直持续到所有元素都按照正确的顺序排列。

选择排序从 array[0] 开始扫描数组,并找到最小值的元素。这个元素的内容然后与 array[0] 的内容交换。在该示例中,array[5] 中存储的 1 是最小的值,所以它与存储在 array[0] 中的 5 交换。这完成了第一趟,现在的数组显示如下:

// value:
1 7 2 8 9 5 

// 下标
0 1 2 3 4 5

该算法后面就是重复该过程。每一次操作需要在N个乐队中找出最大值,一直到排好序,执行了N次复杂度为N的寻找,故时间复杂度为O(n^2).

选择排序需要交换的次数要少于冒泡排序。事实上,正如上栗所示,它每一趟只需要交换一个数据。外部循环的每一次迭代都可以将一个值放置到正确的位置,不仅如此,己经正确的值和数组位置在后面的排序中还无须再次检测。

但是,这里选择排序不使用标记变量,因为即使某个数组位置已经保存了下一个最小的值,从而导致它的值在下一趟排序过程中不会改变,但这并不意味着数组已经完成排序,因为其他值可能尚未移动到它们的正确位置。


JS实现
// JS
function selectionSort(arr{
    var len = arr.length;
    var minIndex, temp;
    for (var i = 0; i < len - 1; i++) {
        minIndex = i;
        for (var j = i + 1; j < len; j++) {
            if (arr[j] < arr[minIndex]) {     // 寻找最小的数
                minIndex = j;                 // 将最小数的索引保存
            }
        }
        temp = arr[i];
        arr[i] = arr[minIndex];
        arr[minIndex] = temp;
    }
    return arr;
}
C++实现
// C++
void selectionSort (int array[], int size)
{
    int startScan, minIndex, minValue;
    for (startScan = 0; startScan < (size - 1); startScan++)
    {
        minIndex = startScan;
        minValue = array[startScan];
        for (int index = startScan + 1; index < size; index++)
        {
            if (array[index] < minValue)
            {
                minValue = array[index];
                minIndex = index;
            }
        }
        array[minIndex] = array[startScan];
        array[startScan] = minValue;
    }
}

总结

局限性:

1.运行时间和输入无关

为了找出最小的元素而扫描一遍数组并不能为下一遍扫描提供什么信息。这种性质在某些情况下是缺点,因为使用选择排序的人可能会惊讶地发现,一个已经有序的数组或是主键全部相等的数组和一个元素随机排列的数组所用的排序时间竟然一样长!我们将会看到,其他算法会更善于利用输入的初始状态。

2.数据移动是最少的

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


小知识

Q:为什么有那么多排序算法,为什么没有一种高效且万能的排序算法呢?

A:原因之一是许多排序算法的性能都和输入模型有很大的关系,因此不同的算法适用于不同应用场景中的不同输入。例如,对于部分有序和小规模的数组应该选择插入排序。其他限制条件,例如空间和重复的主键,也都是需要考虑的因素。

最后

今天的 排序算法之选择排序 就分享到这里,比较简单,明天将分享面试网易遇到的游戏算法,有问题欢迎大家留言,谢谢 ~ 

以上是关于排序算法选择排序的主要内容,如果未能解决你的问题,请参考以下文章

排序算法之冒泡选择插入排序(Java)

选择排序(简单选择排序堆排序的算法思想及代码实现)

《算法》笔记 3 - 选择排序插入排序希尔排序

Java数据结构—排序算法

在第6731次释放指针后双重免费或损坏

三大基础排序算法(冒泡排序,选择排序,插入排序)