1. 程式人生 > >ALDS1_2_B:Selection Sort

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);
        }
    }
}