一步步地分析排序——选择排序

原创 2016年09月25日 20:31:24

前言

本文是对《算法》第四版选择排序所做的笔记,可能因为选择排序比较基础,所以该书将其作为第一个排序算法。虽然算法本身不算复杂,但是通过一个简单算法,详细学习算法的分析过程,还是相当有意义的。本文的脉络如下:

  • 概念(对选择排序做基本介绍)
  • 代码
  • 时间成本
  • 空间成本(主要表现为是不是原地排序算法)
    现在正式进入主题。

概念

  • 什么是选择排序:首先,找到数组里最小的那个元素,然后,将它和数组里第一个元素互换位置(如果第一个元素就是最小的,很自然地,它和自己互换位置)。再然后,在剩余的元素里面,找到最小的元素,将它和第二个元素互换位置,以此类推,往复操作直到排完整个数组。这就是选择排序的概念。
  • 体验过程:来给大家推荐一个网站,点击观看排序算法动态过程:
    http://visualgo.net/sorting

代码(C语言)

书本用的Java语言,而且为了表示通用性,还写成了”Comparable”的形式,我在这里为求简洁,就用C语言来描述。算法重要的是思想,不是语言层面这些东西,而且C语言写出的选择排序,和Java没有很大的区别。代码如下:

//选择排序
void selectSort(int array[], int size)
{
    int i = 0, j = 0;
    for(; i <size; i++)
    {
        int min = i;
        for(j = i+1; j<size; j++)
        {
            if(array[j]<array[min])//(1)号语句,比较数组里的两个元素
            {
                min = j;
            }
        }
        exchange(array, min, i);//(2)号语句,互换数组里的两个元素
    }
}

//互换数组里面索引p和q的元素
void exchange(int array[], int p, int q)
{
    int t = array[p];
    array[p] = array[q];
    array[q] = t;
}

时间成本

我们用下面两个操作来表示选择排序时间成本:比较元素的次数,互换元素的次数。

  • 元素比较:如代码中(1)号语句所示,内层循环每次进行一次比较,所以元素比较次数等于内层循环执行次数。为:1+2+3+…+(N-2)+(N-1) = N(N-1)/2 = O(N²)。
  • 元素互换:如代码中(2)号语句所示,外层循环每次进行一次元素互换,所以元素互换次数等于外层循环次数。为:O(N)。
  • 结论:对于长度为N的数组,选择排序需要进行大约(N²/2)次的比较,N次数组元素的互换。则最终的时间成本为两者和,大O标记表示为:O(N²)。

空间成本

从代码看可以知道,除了互换元素额外使用常数个的(也就一个)临时变量,选择排序所有操作基本都在原数组上进行,所以选择排序是原地排序算法,空间成本不随问题规模增大而增大。

输入对时间成本的影响

由代码可以看出,外层循环,每次对剩余元素进行的遍历(扫描)都不会对下次遍历提供什么帮助。不论输入是怎样的,元素比较和互换的次数不受影响。所以,我们得出以下两点:

  • 不论输入顺序多乱(即使是完全逆序的输入),该算法也不会变得更慢。
  • 不论输入顺序多“好”(即使输入一个已经排好序的数组),算法所需时间没有丝毫减少。一个已经排好序的数组和一个完全逆序的数组,使用选择排序所消耗的时间是一样的。
  • 结论:选择排序时间成本不受输入影响。

其他特性

  • 移动元素的次数:可以看到,不论输入是怎样的,选择排序只会移动元素N次(因为只有最外层的循环才会移动数据,而最外层循环执行N次,只和数组长度有关,与输入的顺序无关)。数据移动的次数和问题规模呈线性的关系。这可能是所有排序算法里面,移动元素次数最少的一个了。
  • 选择排序不会访问当前索引左边的元素:外层循环每执行一次,都将排定一个元素,即将一个元素放在他最终的位置上面,所以,当前索引左边的元素都是已经排好序的,所以选择排序不会访问当前索引左边的元素。
版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

一步步地分析排序——插入排序

一步步地分析插入排序

一步步学习数据结构和算法之选择排序效率分析及java实现

选择排序算法效率分析及实现: public class SelectSort { /** * 选择排序原理:从待排序序列中选出最小的元素,放入到已排好序列 * 元素比较次数:需要比较的次数为...

C++抽象编程——算法分析(1)——选择排序

在递归中,我们介绍了函数fib(n)的两个不同的递归实现(参见:斐波那契数的分析与拓展),该函数计算第n个斐波那契数。第一个是直接基于数学定义: 事实证明这是非常低效的。第二个实现使用加法序列(...
  • redRnt
  • redRnt
  • 2017年05月11日 11:53
  • 265

JavaSE_26th_数组——选择排序

第一次需要遍历所有的元素,以第一个元素为基准,从第二个元素往后找,当找到比第一个小的,就把小的元素对调到第一个来, 直到比对除第一个元素外的所有的元素,这样最小的元素将位于第一个位置。...
  • weqpo
  • weqpo
  • 2017年02月22日 19:56
  • 96

java算法——选择排序

/* * 功能:java实现选择排序法 * */ package Shuzu; public class paixu { public static void main(String[] a...

三个简单的算法——选择排序

(算法用php实现) 先贴代码选择排序

数据结构——选择排序

简介选择排序是一种比较直观的排序方法算法思想选择排序的思想在于(默认升序排序),在一个数组当中,选择这个数组当中最小的元素,将这个元素放在第一位,然后寻找第二小的元素,将这个元素放在第二位。以此类推,...

经典算法与数据结构的c++实现——直接选择排序

因为是经典的算法,所以网上描述一大把,直接上个图,直观些,给记性不好的菜鸟(如我)一点儿提示。 算法很简单,遍历整个数组,依次选取最小值放到数组前面。 下面是代码(欢迎批评指点,之后应该会放到gi...
  • y277an
  • y277an
  • 2016年03月19日 08:47
  • 720

算法初探——选择排序

选择排序(Selection Sort)就是通过n-1次关键字之间的比较,从n-i+1个记录中选择出最小的记录,并和第i个记录做交换。 简单来说就是 ①从第i个记录向后找一个最小的值 ②将找到的...

java专题——选择排序

package 选择排序; public class SelectSort { public static void main(String[] args) { // TODO 自动生成的方...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:一步步地分析排序——选择排序
举报原因:
原因补充:

(最多只允许输入30个字)