选择排序思路
首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。
具体实现方法
①初始状态:无序区为R[0..n-1](共n个元素),有序区为空。
②第1趟排序
设置一个变量i,让i从0至n-2循环的同时,在对比数组中元素i跟元素i+1的大小,如果R[i+1]比R[i]小,则用一个变量k来记住他的位置(即k=i+1)。等到循环结束的时候,我们应该找到了R中最小的那个数的位置了。然后进行判断,如果这个最小元素的不是R的第一个元素,就让第一个元素跟他交换一下值,使R[0..0]和R[1..n-1]分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区。
③第i趟排序
第i趟排序开始时,当前有序区和无序区分别为R[0..i-1]和R[i..n-1]。该趟排序从当前无序区中选出关键字最小的记录 R[k],将它与无序区的第1个记录R交换,使R[0..i]和R分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区。
图1为一个具体例子:(通过寻找最小值的选择排序)
算法性能
时间复杂度
选择排序的交换操作介于 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次,逆序交换n/2次。交换次数比冒泡排序少多了,由于交换所需CPU时间比比较所需的CPU时间多,n值较小时,选择排序比冒泡排序快。
稳定性
选择排序是给每个位置选择当前元素最小的,比如给第一个位置选择最小的,在剩余元素里面给第二个元素选择第二小的,依次类推,直到第n-1个元素,第n个元素不用选择了,因为只剩下它一个最大的元素了。那么,在一趟选择,如果一个元素比当前元素小,而该小的元素又出现在一个和当前元素相等的元素后面,那么交换后稳定性就被破坏了。举个例子,序列5 8 5 2 9,我们知道第一遍选择第1个元素5会和2交换,那么原序列中两个5的相对前后顺序就被破坏了,所以选择排序是一个不稳定的排序算法。
树形
输入输出
输入输出与基本选择排序相同。
思想
利用满二叉树的性质,将输入的数据存放到满二叉树的叶节点,通过比较树中剩余可用节点(从底层的叶节点开始)的大小,每次选择最小的数值(比较复制到二叉树的顶端),并且把最小数值赋给排序数组的前端,把最小数值原来叶节点的位置设置为不可用;依次循环直至最后一个可用叶节点。
堆
堆分为大根堆和小根堆,是完全二叉树。大根堆的要求是每个节点的值都不大于其父节点的值,即A[PARENT[i]] >= A[i]。在数组的非降序排序中,需要使用的就是大根堆,因为根据大根堆的要求可知,最大的值一定在堆顶。
既然是堆排序,自然需要先建立一个堆,而建堆的核心内容是调整堆,使二叉树满足堆的定义(每个节点的值都不大于其父节点的值)。接下来就是调堆和循环调堆,具体参见堆排序。
思想含义
n个记录的文件的直接选择排序可经过n-1趟直接选择排序得到有序结果:
①初始状态:无序区为R[1..n],有序区为空。
②第1趟排序
在无序区R[1..n]中选出关键字最小的记录R[k],将它与无序区的第1个记录R交换,使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记住它在数组中的位置(下标),等到循环结束的时候,我们应该找到了最小的那个数的下标了,然后进行判断,如果这个元素的下标不是第一个元素的下标,就让第一个元素跟他交换一下值,这样就找到整个数组中最小的数了。然后找到数组中第二小的数,让他跟数组中第二个元素交换一下值,以此类推。
排序特点复杂
选择排序的交换操作介于 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
最后排序结果 13 27 38 49 49 65 76 97
#include #include void swap(int *a, int *b){ int temp; temp = *a; *a = *b; *b = temp;}void select_sort(int A[], int n){ register int i, j, min, m; for(i=0; ij++) { if(A[min] > A[j]) { min = j; } } if(min != i) { swap(&A[min], &A[i]); printf("第%d趟排序结果为:n", i+1); for(m=0; m 0) { printf(" "); } printf("%d", A[m]); } printf("n"); } }}int main(void){ int n; while(scanf("%d", &n) != EOF) { int i; int *A = (int *)malloc(sizeof(int)*n); for(i=0; i 0) { printf(" "); } printf("%d", A[i]); } printf("n"); } return 0;} 语言C#
C#语言选择排序算法:
static void 选择排序(int [] group) { int temp; int pos = 0; for (int i = 0; i < group.Length-1; i++) { pos = i; for (int j = i + 1; j < group.Length; j++) { if (group[j] < group[pos]) { pos = j; } } //第i个数与最小的数group[pos]交换 temp = group[i]; group[i] = group[pos]; group[pos] = temp; } }C
C语言:void select_sort(int *a, int n){ register int i, j, min, t; for( i =0; i < n -1; i ++) { min = i; //查找最小值 for( j = i +1; j < n; j ++) if( a[min] > a[j]) min = j; //交换 if(min != i) { t = a[min]; a[min] = a[i]; a[i] = t; } } }
C++选择排序算法:
#include#include#includeusing namespace std;const int N=10; int main(){ int a[N], i, j, temp, b; srand(time(NULL)); for(i=0;icout<<
选择排序法的第一层循环从起始元素开始选到倒数第二个元素,主要是在每次进入的第二层循环之前,将外层循环的下标赋值给临时变量,接下来的第二层循环中,如果发现有比这个最小位置处的元素更小的元素,则将那个更小的元素的下标赋给临时变量,最后,在二层循环退出后,如果临时变量改变,则说明,有比当前外层循环位置更小的元素,需要将这两个元素交换.
Java
JAVA选择排序算法:
public static void selectSort(int a[]){ int minIndex = 0; int temp = 0; if((a==null)||(a.length==0)) return; for(int i=0; i
PASCAL选择排序算法:
procedure ssort(a:array of integer);{a为元素数组}var i,j,k,temp:integer;beginfor i:=n downto 2 do{共n-1轮选择}begink:=1;for j:=1 to i doif a[j]>a[k] then k:=j;{第i轮,记录前i个数中最大的}begin {复合语句需要加入begin和end}temp:=a[k];{把最大的与倒数第i个交换}a[k]:=a[i];a[i]:=temp;end;end;end.
public class Test
{
public static int[] a = { 8,32,1,9,5,7,12,0,4,3 }; //预设整数数组
public static void main(String args[])
{
int index = a.length;//数组长度
System.out.print("排序前: ");
for (int i = 0; i < index; i++)//遍历数组
System.out.printf("%3s",a[i]);
System.out.println("");
//选择排序
SelectSort(index);
System.out.print("排序后: ");
for (int i = 0; i < index; i++)
System.out.printf("%3s",a[i]);
System.out.println("");
}
public static void SelectSort(int index)
{
for (int i = 0; i < index - 1; i++)
{
for (int j = i+1; j < index; j++)
{
if(a[i]>a[j])//i、j分别代表前、后角标,假如数组i角标所在的值大于j的值,就把i的值赋值给临存变量temp,两者再进行位置置换。
{
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
System.out.print("排序中: ");
for (int k = 0; k < index; k++)
System.out.printf("%3s",a[k]);
System.out.println("");
}
}
}
Perl
PERL选择排序算法:
#!/usr/bin/perlsub select_sort{my (*array)=@_;$length=@array;for($i=0;$i<$length-1;$i++){$min=$i;for($j=$i+1;$j<$length;$j++){if($array[$j]<$array[$min]){$min=$j;}if($min!=$i){$temp=$array[$i];$array[$i]=$array[$min];$array[$min]=$temp;}}return @array;}php
PHP选择排序算法:
'.$array[$min].'-->'; for ($j=$i+1;$j<$count;$j++) { //由小到大排列 if ($array[$min]>$array[$j]) { //表明当前最小的还比当前的元素大 $min = $j; //赋值新的最小的 } } echo $array[$min].'coco
'; /* swap $array[$i] and $array[$min] 即将当前内循环的最小元素放在$i位置上*/ if($min!=$i) { $temp = $array[$min]; $array[$min] = $array[$i]; $array[$i] = $temp; } } return $array;}$old_array = array(3,4,1,6,5,2);$new_array = selection_sort($old_array);print_r($new_array);?>vb
vb选择排序算法:
Private Sub xzPaiXu(a() As Double, sheng As Boolean) 'a为需要排序的数组,sheng为True则为升序排列,为False,则为降序排列。 Dim i As Integer, j As Integer Dim temp As Double Dim m As Integer For i = LBound(a) To UBound(a) - 1 '进行数组大小-1轮比较 m = i '在第i轮比较时,假定第 'i个元素为最值元素 For j = i + 1 To UBound(a) '在剩下的元素中找出最 '值元素的下标并记录在m中 If sheng Then '若为升序,则m记录最小元素 '下标,否则记录最大元素下标 If a(j) < a(m) Then m = j Else If a(j) > a(m) Then m = j End If Next j '将最值元素与第i个元素交换 temp = a(i) a(i) = a(m) a(m) = temp Next iEnd Sub
算法
首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。n再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。n重复第二步,直到所有元素均排序完毕。



















