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

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

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

一步步地分析插入排序
  • u010707039
  • u010707039
  • 2016年09月28日 15:14
  • 1207

选择排序原理分析及Java实现

选择排序: 它的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。 选择排序是不稳定的排序方法(比如序列[5, 5, 3]第一次就...
  • dylanzr
  • dylanzr
  • 2016年04月11日 15:56
  • 890

排序算法之 选择排序 及其时间复杂度和空间复杂度

其实选择排序是非常简单的,和冒泡排序有异曲同工之妙。就是把元素分成两部分,一部分是有序的,另外一部分是无序的;每次循环从无序的元素中选取一个元素放到有序的元素中,依次循环到最后把所有元素都放到了有序那...
  • YuZhiHui_No1
  • YuZhiHui_No1
  • 2015年03月17日 11:44
  • 6809

数据结构 JAVA描述(十一) 选择排序(直接选择排序,树形选择排序,堆排序)

直接选择排序 置i初值为0 当i < n-1时,重复下列步骤在无序子序列中{a[i], ……a[n-1]}中选出最小的a[min] 若min!=i,则交换 i++...
  • liuquan0071
  • liuquan0071
  • 2016年01月05日 14:01
  • 539

ACM——p2016数据的交换输出(选择排序,选择最小数与第一个交换)

Problem Description 输入n(n   Input 输入数据有多组,每组占一行,每行的开始是一个整数n,表示这个测试实例的数值的个数,跟着就是n个整数。n=0表示输入的结束,不做处...
  • qq_31678809
  • qq_31678809
  • 2016年09月26日 12:29
  • 372

一步步地分析排序——堆排序与优先队列

前言 本文是对《算法》第四版优先队列章节做的笔记,在学习并理解了书本“优先队列”这一节后,回过头来看这些知识点,总体来说,不算很难,至少没有什么在智商上难以逾越的鸿沟,然而想要彻底地理解这一节的所有...
  • u010707039
  • u010707039
  • 2017年08月27日 10:53
  • 80

常见排序算法(二)(选择排序)

本文介绍排序算法中的选择排序,选择排序分为三种:直接选择排序、树形选择排序(锦标赛排序)、堆排序,并对每种排序算法进行了分析,附带java实现代码。...
  • sysukehan
  • sysukehan
  • 2016年09月25日 14:01
  • 1909

数据结构之排序:直接选择排序

选择排序的主要思想是每一趟从待排序序列中选取一个关键值最小的记录,即第1趟从n个记录中选取关键字值最小的记录,第2趟从剩下的n-1个记录中选取关键字值最小的记录,知道整个序列中的记录都选完为止。由选取...
  • u011080472
  • u011080472
  • 2016年05月02日 17:42
  • 408

选择式排序法之选择排序法实现 -java版

计算算法时间复杂度比冒泡快一点 选择排序法核心思想是,第一次从R[0] ~R[n-1]中选择最小值然后与R[0]交换,第二次从R[1] ~R[n-1]中选取最小值与R[1]交换………第i次呢就是从R...
  • JQ_AK47
  • JQ_AK47
  • 2015年07月03日 16:54
  • 1022

三种基本排序-冒泡排序、直接插入排序、选择排序

冒泡排序(从大到小)       原理:对于n个数,需要进行n-1次扫描,每次扫描通过相邻两个数的比较,找出最大的数,放到数列顶部。      程序:    1.冒泡排序1:每次扫描把下一个元素和最前...
  • chao360559040
  • chao360559040
  • 2010年10月29日 11:25
  • 14106
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:一步步地分析排序——选择排序
举报原因:
原因补充:

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