Processing math: 25%
NOIP学习小站
西安交通大学附属中学航天学校

选择排序

选择排序(Selection Sort)是一种简单直观的排序算法。算法的处理过程是:第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到未排序序列的首部(也就是已排序序列末尾的下一个位置)。以此类推,直到处理完所有待排序的数据元素。可知选择排序是将序列前面部分变得有序,并且将有序的区间逐步扩大直到整个序列有序。

n 个数据选择排序,只需要经过 n-1 趟选择最小(大)值并交换的处理,因为经过 n-1 趟处理后,只剩下最后一个数,而这个数就是整个序列的最小(大)值,不需要再处理了。可以使用打擂求极值的策略,每次找到未排序部分的最小(大)值,不过这里记录的是最小(大)值所在的下标:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
//选择排序:对数组的r[0]~r[n-1]区域排序(升序排序)
void SelectSort(int r[],int n){
for(int i=0;i<n-1;i++){
int k = i; //k记录r[i]~r[n-1]最小值的下标
for(int j=i+1;j<n;j++){
//新找到一个更符合条件的数据,更新记录最小值下标的变量k
if(r[j]<r[k]) k = j;
}
//新找到一个不是初始值i的下标k,交换r[i]和r[k]
if(k != i){
int t = r[k];r[k] = r[i];r[i] = t;
}
}
}
//调用方法举例:SelectSort(a,10);
//调用方法举例:SelectSort(a,n);
//选择排序:对数组的r[0]~r[n-1]区域排序(升序排序) void SelectSort(int r[],int n){ for(int i=0;i<n-1;i++){ int k = i; //k记录r[i]~r[n-1]最小值的下标 for(int j=i+1;j<n;j++){ //新找到一个更符合条件的数据,更新记录最小值下标的变量k if(r[j]<r[k]) k = j; } //新找到一个不是初始值i的下标k,交换r[i]和r[k] if(k != i){ int t = r[k];r[k] = r[i];r[i] = t; } } } //调用方法举例:SelectSort(a,10); //调用方法举例:SelectSort(a,n);
//选择排序:对数组的r[0]~r[n-1]区域排序(升序排序)
void SelectSort(int r[],int n){
	for(int i=0;i<n-1;i++){
		int k = i;		//k记录r[i]~r[n-1]最小值的下标 
		for(int j=i+1;j<n;j++){
			//新找到一个更符合条件的数据,更新记录最小值下标的变量k 
			if(r[j]<r[k]) k = j;
		}
		//新找到一个不是初始值i的下标k,交换r[i]和r[k] 
		if(k != i){
			int t = r[k];r[k] = r[i];r[i] = t;
		}
	}
}
//调用方法举例:SelectSort(a,10);
//调用方法举例:SelectSort(a,n);

仿照 sort 函数的写法,用两个指针作为函数参数来指定排序的区域:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
//选择排序:对指针begin~end区域排序(升序排序,不包括end)
void SelectSort(int *begin,int *end){
for(int *p = begin;p+1<end;p++){
int *k = p; //k记录 p ~ end-1 区域最小值的指针
for(int *q = p+1;q<end;q++){
//新找到一个更符合条件的数据,更新记录最小值下标的指针k
if(*q < *k) k = q;
}
//新找到一个不是初始值p的指针k,交换 *p 和 *k
if(k != p){
int t = *k;*k = *p;*p = t;
}
}
}
//调用方法举例:SelectSort(a,a+10);
//调用方法举例:SelectSort(a,a+n);
//调用方法举例:SelectSort(a+1,a+n+1);
//选择排序:对指针begin~end区域排序(升序排序,不包括end) void SelectSort(int *begin,int *end){ for(int *p = begin;p+1<end;p++){ int *k = p; //k记录 p ~ end-1 区域最小值的指针 for(int *q = p+1;q<end;q++){ //新找到一个更符合条件的数据,更新记录最小值下标的指针k if(*q < *k) k = q; } //新找到一个不是初始值p的指针k,交换 *p 和 *k if(k != p){ int t = *k;*k = *p;*p = t; } } } //调用方法举例:SelectSort(a,a+10); //调用方法举例:SelectSort(a,a+n); //调用方法举例:SelectSort(a+1,a+n+1);
//选择排序:对指针begin~end区域排序(升序排序,不包括end)
void SelectSort(int *begin,int *end){
    for(int *p = begin;p+1<end;p++){
        int *k = p;        //k记录 p ~ end-1 区域最小值的指针 
        for(int *q = p+1;q<end;q++){
            //新找到一个更符合条件的数据,更新记录最小值下标的指针k 
            if(*q < *k) k = q;
        }
        //新找到一个不是初始值p的指针k,交换 *p 和 *k 
        if(k != p){
            int t = *k;*k = *p;*p = t;
        }
    }
}
//调用方法举例:SelectSort(a,a+10);
//调用方法举例:SelectSort(a,a+n);
//调用方法举例:SelectSort(a+1,a+n+1);

选择排序的时间复杂度是 O(n^2)。如下图所示可知选择排序是不稳定的排序算法:

如图所示,选择排序结束后,第 1 个 6(红色文字标识)出现在第 2 个 6 的后面,可见选择排序是不稳定的。


这里仿照 sort 函数实现带自定义比较函数的选择排序函数,帮助大家理解 sort 函数是如何通过比较函数实现自定义排序的:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
#include<iostream>
using namespace std;
const int N = 110;
int a[N];
//选择排序:对指针 begin~end 区间进行升序排序,不包含end
void SelectSort(int *begin ,int *end){
for(int *p = begin;p+1<end;p++){
int *k = p;
for(int *q = p+1;q<end;q++){
if(*q < *k) k = q;
}
if(k != p){
int t = *k;*k = *p;*p = t;
}
}
}
//选择排序:对指针 begin~end 区间进行排序,不包含end
//第三个参数cmpfun是排序比较函数,注意这个参数的类型是函数
void SelectSort(int *begin ,int *end ,bool(*cmpfun)(int a ,int b) ){
for(int *p = begin;p+1<end;p++){
int *k = p;
for(int *q = p+1;q<end;q++){
//调用比较函数cmpfun,由比较函数返回值决定是否更新k
if(cmpfun(*q,*k)) k = q;
}
if(k != p){
int t = *k;*k = *p;*p = t;
}
}
}
//比较函数:降序排序
bool cmp(int a,int b){
return a>b;
}
//比较函数:升序排序
bool cmp2(int a,int b){
return a<b;
}
int main(){
int n;
cin>>n;
for(int i=0;i<n;i++){
cin>>a[i];
}
//调用没有比较函数的SelectSort
SelectSort(a,a+n);
for(int i=0;i<n;i++){
cout<<a[i]<<" ";
}
cout<<endl;
//调用有比较函数的SelectSort
SelectSort(a,a+n,cmp);
for(int i=0;i<n;i++){
cout<<a[i]<<" ";
}
cout<<endl;
//调用有比较函数的SelectSort
SelectSort(a,a+n,cmp2);
for(int i=0;i<n;i++){
cout<<a[i]<<" ";
}
cout<<endl;
return 0;
}
#include<iostream> using namespace std; const int N = 110; int a[N]; //选择排序:对指针 begin~end 区间进行升序排序,不包含end void SelectSort(int *begin ,int *end){ for(int *p = begin;p+1<end;p++){ int *k = p; for(int *q = p+1;q<end;q++){ if(*q < *k) k = q; } if(k != p){ int t = *k;*k = *p;*p = t; } } } //选择排序:对指针 begin~end 区间进行排序,不包含end //第三个参数cmpfun是排序比较函数,注意这个参数的类型是函数 void SelectSort(int *begin ,int *end ,bool(*cmpfun)(int a ,int b) ){ for(int *p = begin;p+1<end;p++){ int *k = p; for(int *q = p+1;q<end;q++){ //调用比较函数cmpfun,由比较函数返回值决定是否更新k if(cmpfun(*q,*k)) k = q; } if(k != p){ int t = *k;*k = *p;*p = t; } } } //比较函数:降序排序 bool cmp(int a,int b){ return a>b; } //比较函数:升序排序 bool cmp2(int a,int b){ return a<b; } int main(){ int n; cin>>n; for(int i=0;i<n;i++){ cin>>a[i]; } //调用没有比较函数的SelectSort SelectSort(a,a+n); for(int i=0;i<n;i++){ cout<<a[i]<<" "; } cout<<endl; //调用有比较函数的SelectSort SelectSort(a,a+n,cmp); for(int i=0;i<n;i++){ cout<<a[i]<<" "; } cout<<endl; //调用有比较函数的SelectSort SelectSort(a,a+n,cmp2); for(int i=0;i<n;i++){ cout<<a[i]<<" "; } cout<<endl; return 0; }
#include<iostream>
using namespace std;
const int N = 110;
int a[N]; 

//选择排序:对指针 begin~end 区间进行升序排序,不包含end 
void SelectSort(int *begin ,int *end){
    for(int *p = begin;p+1<end;p++){
        int *k = p;
        for(int *q = p+1;q<end;q++){
            if(*q < *k) k = q;
        }
        if(k != p){
            int t = *k;*k = *p;*p = t;
        }
    }
}

//选择排序:对指针 begin~end 区间进行排序,不包含end
//第三个参数cmpfun是排序比较函数,注意这个参数的类型是函数 
void SelectSort(int *begin ,int *end ,bool(*cmpfun)(int a ,int b) ){
    for(int *p = begin;p+1<end;p++){
        int *k = p;
        for(int *q = p+1;q<end;q++){
        	//调用比较函数cmpfun,由比较函数返回值决定是否更新k 
            if(cmpfun(*q,*k)) k = q;
        }
        if(k != p){
            int t = *k;*k = *p;*p = t;
        }
    }
}

//比较函数:降序排序
bool cmp(int a,int b){
	return a>b;
}

//比较函数:升序排序
bool cmp2(int a,int b){
	return a<b;
}

int main(){ 
	int n;
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>a[i];
	}
	
	//调用没有比较函数的SelectSort 
	SelectSort(a,a+n);
	for(int i=0;i<n;i++){
		cout<<a[i]<<" ";
	}
	cout<<endl;
	
	//调用有比较函数的SelectSort
	SelectSort(a,a+n,cmp);
	for(int i=0;i<n;i++){
		cout<<a[i]<<" ";
	}
	cout<<endl;

	//调用有比较函数的SelectSort
	SelectSort(a,a+n,cmp2);
	for(int i=0;i<n;i++){
		cout<<a[i]<<" ";
	}
	cout<<endl;
	
	return 0;
} 

登录

注册