算法—1.选择排序
1.基本思想
首先,找到数组中最小的那个元素,其次,将它和数组的第一个元素交换位置(如果第一个元素就是最小元素那么它就和自己交换)。再次,在剩下的元素中找到最小的元素,将它与数组的第二个元素交换位置。如此往复,直到将整个数组排序。这种方法叫做选择排序,因为它在不断地选择剩余元素之中的最小者。
2.具体算法
/** * 选择排序 * @author huazhou * */ public class Selection extends Model{ //将a[]按升序排列 public void sort(Comparable[] a){ int N = a.length; //数组长度 //将a[i]和a[i+1...N]中最小的元素交换 for (int i = 0; i < N; i++) { int min = i; //最小元素的索引 for (int j = i+1; j < N; j++) { if(less(a[j], a[min])){ min = j; } } exch(a, i, min); } } }
//对元素进行比较,如果v比w小则返回true protected boolean less(Comparable v, Comparable w){ return v.compareTo(w) < 0; } //将元素交换位置 protected void exch(Comparable[] a, int i, int j){ Comparable t = a[i]; a[i] = a[j]; a[j] = t; }
该算法将第i小的元素放到a[i]之中。数组的第i个位置的左边是i个最小的元素且它们不会再被访问。
3.算法分析
命题:对于长度为N的数组,选择排序需要大约N2/2次比较和N次交换
证明:可以通过算法的排序轨迹来证明这一点。我们用一张NxN的表格来表示排序的轨迹(见下图),其中每个非灰色字符都表示一次比较。表格中大约一半的元素不是灰色的——即对角线和其上部分的元素。对角线上的每个元素都对应着一次交换。通过查看代码我们可以更精确地得到,0到N-1的任意i都会进行一次交换和N-1-i次比较,因此总共有N次交换以及∑N-1i=0(N-1-i)=(N-1)+(N-2)+...+2+1+0=N(N-1)/2~N2/2次比较。
4.总结
总的来说,选择排序是一种很容易理解和实现的简单排序算法,它有两个很鲜明的特点。
运行时间和输入无关。为了找出最小的元素而扫描一遍数组并不能为下一遍扫描提供什么信息。这种性质在某些情况下是缺点,因为使用选择排序的人可能会惊讶地发现,一个已经有序的数组或是主键全部相等的数组和一个元素随机排列的数组所用的排序时间竟然一样长!我们将会看到,其他算法会更善于利用输入的初始状态。
数据移动是最少的。每次交换都会改变两个数组元素的值,因此选择排序用了N次交换——交换次数和数组的大小是线性关系。我们将研究的其他任何算法都不具备这个特征(大部分的增长数量级都是线性对数或是平方级别)。
运行:
项目是用androidstudio开发的,原因是运行项目需要用到重定位输入符<,eclipse和as直接运行都无法带上此符号,只能在命令窗口运行,as的自带命令窗口比较方便。运行方法,先在IDE编译并运行一次,然后在as的命令窗口cd进入sort | build | classes | main,然后输入java Example < D:\tiny.txt,此D:为tiny.txt的完整路径。以下是我机器上的运行结果:
PS:
此次算法文章皆为原创,转载请注明出处,内容皆出自Robert Sedgewick的《算法》第四版。
【源码下载】