ALDS1_2_B:Selection Sort


选择排序法

重复执行N-1次下述处理

1.找出未排序部分最小值的位置minj。

2.将minj位置的元素与未排序部分的起始元素交换。

以数组A={5,4,8,7,9,3,1}为例,我们对其使用选择排序法时,排序过程如图3.6所示。


    步骤0为初始状态,此时所有元素均属于未排序部分。

    在步骤1中,我们找出未排序部分最小值的位置(minj=6),然后将该位置的元素A[6](=1)与未排序部分的起始元素A[0](=5)进行交换。这样一来,已排序部分就增加了一个元素。

    在步骤2中,找出未排序部分最小值的位置(minj=5),然后将该位置的元素A[5](=3)与未排序部分的起始元素A[1](=4)进行交换。后边的步骤同理,从数组开头按有小到大的顺序逐个确定每个位置的值。

    实现选择排序法时需要的主要变量如图3.7所示。


A[N]             长度为N的整型数组

i                    循环变量,表示未排序部分的开头元素,从数组开头向末尾移动

minj             各轮循环处理中,第i号到第N-1号元素中最小值的位置

j                    循环变量,用来查找未排序部分中最小值的位置(minj)

    在每一轮i的循环中,通过j自增来遍历A[i]到A[N-1],从而确定minj。确定minj后,让起始元素A[i]与最小值元素A[minj]进行交换。

考察

    假设现在有一组由数字和字母组成的数据,我们试着用选择排序法对其进行升序排列。在如图3.8所示的例子里,我们"以数字为基准"进行排序,该排序数组中2个元素带有数字"3",初始状态下其顺序为3H->3D。


    我们会发现,排序结束后这两个元素的顺序反了过来,变成了3D->3H。也就是说,由于选择排序法会直接交换两个不相邻的元素,所以属于不稳定的排序算法。

    然后再来看看选择排序法的复杂度。假设数据总数为N,那么无论在何种情况下,选择排序法都需要进行(N-1)+(N-2)+...+1=(N^2-N)/2次比较运算,用于搜索未排序部分的最小值。因此该算法的复杂度与N^2基本成正比,即复杂度数量级为O(N^2)。

    冒泡排序法与选择排序法相比,一个从局部入手减少逆序元素,一个放眼大局逐个选择最小值,二者思路大不相同。但是,它们又都有着"通过i次外层循环,从数据中顺次求出i个最小值"的相同特征。相对地,插入排序法是通过i次外层循环,直接将原数组的i个元素重新排序。另外,不含flag的简单冒泡排序法和选择排序法不依赖数据,即比较运算的次数(算法复杂度)不受输入数据影响,而插入算法在执行时却依赖数据,处理某些数据时具有很高的效率。

C语言版本:

#include<stdio.h>

int selectionSort(int A[],int N){
	int i,j,t,sw=0,minj;
	for(i=0;i<N-1;i++){
		minj=i;
		for(j=i;j<N;j++){
			if(A[j]<A[minj])
				minj=j;
		}
		t=A[i];
		A[i]=A[minj];
		A[minj]=t;
		if(i!=minj)
			sw++;
	}
	return sw;
}

int main(){
	int A[100],N,i,sw;
	
	scanf("%d",&N);
	for(i=0;i<N;i++)
		scanf("%d",&A[i]);
		
	sw = selectionSort(A,N);
	for(i=0;i<N;i++){
		if(i>0)
			printf(" ");
		printf("%d",A[i]);
	}
	printf("\n");
	printf("%d\n",sw);
	
	return 0;
}

C++版本:

#include <iostream>
using namespace std;
 
int main(int argc, const char * argv[]) {
    //read
    int n;
    cin>>n;
    int a[n];
    int count = 0;
     
    for(int i=0;i<n;i++){
        cin>>a[i];
    }
     
    //solve
    for(int i=0;i<n;i++){
        int minj = i;
        for(int j=i;j<n;j++){
            if(a[j]<a[minj]){
                minj = j;
            }
        }
        if(a[i]!=a[minj]){
            int tmp = a[i];
            a[i]=a[minj];
            a[minj]=tmp;
            count++;
        }
    }
    //output
    cout<<a[0];
    for(int i = 1;i<n;i++){
        cout<<' '<<a[i];
    }
    cout<<endl;
    cout<<count<<endl;
}

JAVA版本:

import java.io.*;
class Main
{
    public static void main(String args[])throws IOException
    {
    BufferedReader input=new BufferedReader(new InputStreamReader(System.in));
    int n=Integer.parseInt(input.readLine());
    String str=input.readLine();
    String str_ary[]=str.split(" ");
    int a[]=new int[n];
    int x=0;
    for(int i=0;i<n;i++)
        {
        a[i]=Integer.parseInt(str_ary[i]);
        }
    for(int i=0;i<n;i++)
        {
        int mini=i;
        int lowkey=a[i];
        for(int j=i;j<n;j++)
            {
            if(a[j]<lowkey)
                {
                mini=j;
                lowkey=a[j];
                 
                }
             
            }
        if(a[i]>lowkey)
            {
        int temp=a[i];
        a[i]=a[mini];
        a[mini]=temp;
            }
        else x++;
        }   
    for(int i=0;i<n;i++)
        {
        System.out.print(a[i]+((i!=n-1)?" ":"\n"));
        }
    System.out.println(n-x);
    }
}

Python版本:

n = int(input())
*A, = map(int, input().split())
ans = 0
for i in range(n):
    j = A[i:].index(min(A[i:])) + i
    A[i], A[j] = A[j], A[i]
    if i != j:
        ans += 1
print(*A)
print(ans)

PHP版本:

<?php
$N=(int)trim(fgets(STDIN));
$A=explode(' ',trim(fgets(STDIN)));

$trade=0;
for($i=0;$i<$N;$i++){
  $mini=$i;
  for($j=$i;$j<$N;$j++) if($A[$j]<$A[$mini]) $mini=$j;
  if($mini==$i) continue;
  list($A[$i],$A[$mini])=[$A[$mini],$A[$i]];
  ++$trade;
}
echo implode(' ',$A),PHP_EOL,$trade;
?>

JavaScript版本:

var input = require('fs').readFileSync('/dev/stdin', 'utf8');
var lines = input.split('\n');
var n = lines[0];

var A = lines[1].split(' ').map(function(i) {
	return i - 0;
});

var cnt = 0;
for (var i = 0; i < n; i++) {
	var min = i;
	for (var j = i; j < n; j++) {
		if (A[j] < A[min])
			min = j;
	}

	if (min == i)
		continue;

	var tmp = A[i];
	A[i] = A[min];
	A[min] = tmp;
	cnt++;
}  

console.log(A.join(' '));
console.log(cnt);

C#版本:

using System;
 
namespace Sort
{
    class Progarm
    {
        static void Main()
        {
            int n = int.Parse(Console.ReadLine());
            var a = Array.ConvertAll(Console.ReadLine().Split(), int.Parse);
            int c = 0;
            for( int i = 0; i < n; i++)
            {
                int m = i;
                for (int j = i; j < n; j++)
                    if (a[j] < a[m]) m = j;
                int t = a[i];
                a[i] = a[m]; a[m] = t;
                if (i != m) c++;
            }
            var r = Array.ConvertAll(a, e => e.ToString());
            Console.Write("{0}\n{1}\n", string.Join(" ", r), c);
        }
    }
}

























  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值