选择排序算法(java实现)

时间:2022-08-07 11:12:49

一、简介

每一趟从待排序的数据元素中选出最小(或最大)的一个元素,顺序放在已排好序的数列的最后,直到全部待排序的数据元素排完。 选择排序是不稳定的排序方法。

排序算法即解决以下问题的算法: 输入:n个数的序列<a1,a2,a3,...,an>。 输出:原序列的一个重排<a1*,a2*,a3*,...,an*>;,使得a1*<=a2*<=a3*<=...<=an*


二、思想

排序算法有很多,包括插入排序,冒泡排序,堆排序,归并排序,选择排序,计数排序,基数排序,桶排序,快速排序等。插入排序,堆排序,选择排序,归并排序和快速排序,冒泡排序都是比较排序,它们通过对数组中的元素进行比较来实现排序,其他排序算法则是利用非比较的其他方法来获得有关输入数组的排序信息。

n个记录的文件的直接选择排序可经过n-1趟直接选择排序得到有序结果: ①初始状态:无序区为R[1..n],有序区为空。 ②第1趟排序 在无序区R[1..n]中选出关键字最小的记录R[k],将它与无序区的第1个记录R[1]交换,使R[1..1]和R[2..n]分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区。 …… ③第i趟排序 第i趟排序开始时,当前有序区和无序区分别为R[1..i-1]和R(i..n)。该趟排序从当前无序区中选出关键字最小的记录 R[k],将它与无序区的第1个记录R交换,使R[1..i]和R分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区。 常见的选择排序细分为简单选择排序、树形选择排序(锦标赛排序)、堆排序。上述算法仅是简单选择排序的步骤。

三、通俗的解释 对比数组中前一个元素跟后一个元素的大小,如果后面的元素比前面的元素小则用一个变量k来记住他的位置,接着第二次比较,前面“后一个元素”现变成了“前一个元素”,继续跟他的“后一个元素”进行比较如果后面的元素比他要小则用变量k记住它在数组中的位置(下标),等到循环结束的时候,我们应该找到了最小的那个数的下标了,然后进行判断,如果这个元素的下标不是第一个元素的下标,就让第一个元素跟他交换一下值,这样就找到整个数组中最小的数了。然后找到数组中第二小的数,让他跟数组中第二个元素交换一下值,以此类推。
  
排序特点复杂 选择排序算法(java实现)

排序算法复杂度对比

选择排序的交换操作介于 0 和 (n - 1) 次之间。选择排序的比较操作为 n (n - 1) / 2 次之间。选择排序的赋值操作介于 0 和 3 (n - 1) 次之间。
比较次数O(n^2),比较次数与关键字的初始状态无关,总的比较次数N=(n-1)+(n-2)+...+1=n*(n-1)/2。交换次数O(n),最好情况是,已经有序,交换0次;最坏情况是,逆序,交换n-1次。交换次数比冒泡排序少多了,由于交换所需CPU时间比比较所需的CPU时间多,n值较小时,选择排序比冒泡排序快。 其他排序算法的复杂度如右图所示。 稳定 选择排序是给每个位置选择当前元素最小的,比如给第一个位置选择最小的,在剩余元素里面给第二个元素选择第二小的,依次类推,直到第n-1个元素,第n个元素不用选择了,因为只剩下它一个最大的元素了。那么,在一趟选择,如果一个元素比当前元素小,而该小的元素又出现在一个和当前元素相等的元素后面,那么交换后稳定性就被破坏了。比较拗口,举个例子,序列5 8 5 2 9,我们知道第一遍选择第1个元素5会和2交换,那么原序列中2个5的相对前后顺序就被破坏了,所以选择排序不是一个稳定的排序算法。 排序实例 初始关键字 [49 38 65 97 76 13 27 49] 第一趟排序后 13 [38 65 97 76 49 27 49] 第二趟排序后 13 27 [65 97 76 49 38 49] 第三趟排序后 13 27 38 [97 76 49 65 49] 第四趟排序后 13 27 38 49 [76 97 65 49 ] 第五趟排序后 13 27 38 49 49 [97 65 76] 第六趟排序后 13 27 38 49 49 65 [97 76] 第七趟排序后 13 27 38 49 49 65 76 [97] 最后排序结果 13 27 38 49 49 65 76 97

四、代码实现(java):

/**
* 选择排序
*
* @author pengcx
*
*/
public class Selection {

public static void main(String[] args) {
String[] a = { "d", "a", "w", "b", "q" };
Selection.sort(a);
show(a);
}

/**
* 排序数组a
*
* @param a
* 排序的数组a
*/
public static void sort(Comparable[] a) {
int N = a.length;
for (int i = 0; i < N; i++) {
// 默认最小元素为a[i]
int min = i;
// 从a[i+1]至a[N]中寻找到最小元素
for (int j = i + 1; j < N; j++) {
// 如果a[j]比a[min]小,则当前最小元素为a[j]
if (less(a[j], a[min])) {
min = j;
}
}
// 将a[min]于a[i]交换
exch(a, i, min);
}
}

/**
* 交换数组a中的第i个元素和第j个元素
*
* @param a
* 交换元素的数组a
* @param i
* 交换元素的索引i
* @param j
* 交换元素的索引j
*/
private static void exch(Comparable[] a, int i, int j) {
Comparable swap = a[i];
a[i] = a[j];
a[j] = swap;
}

/**
* 比较v和w的大小
*
* @param v
* 比较的元素v
* @param w
* 比较的元素w
* @return 大小标识
*/
private static boolean less(Comparable v, Comparable w) {
return (v.compareTo(w) < 0);
}

private static void show(String[] a) {
for (int i = 0; i < a.length; i++) {
System.out.print(a[i]);
}
}
}