选择排序及其优化

 一、原始的选择排序

       选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。

#include<iostream>
using namespace std;
void selectionSort(int arr[],int n)/* 选择排序*/
{
	for(int i=0;i<n;i++)    
/*从第一个元素arr[0]到最后一个元素arr[n-1],共进行n次排序(也可以只循环至倒数第二个元素,即n-1次排序,因为arr[j]总是从arr[i+1]开始)*/
       {        int minIndex=i;/*选每次循环的首个元素*/
		for(int j=i+1;j<n;j++)
		{
			if(arr[j]<arr[minIndex]){
				minIndex=j; /*寻找到每次循环中的最小值*/
			}
		} 
		swap(arr[i],arr[minIndex]);/*每次循环都将余下中的最小值放在的第i+1个元素*/	}  }
int main()
{
   int a[10]={3,9,-1,4,0,8,68,-41,5,10};
   selectionSort(a,10);
   for(int i=0;i<10;i++)
   {
   	cout<<a[i]<<' ';
	}	
	return 0;
} 

主函数可以改成自己需要的形式,这里举例最简单的情况。

二、选择排序的优化:

1.使用模板,将selectionSort()中数组定义为任意类型可用

#include<iostream>
using namespace std;

struct Student{
	string name;
	int score;
	bool operator<(const Student &otherStudent){
	 return score!=otherStudent.score ? score <otherStudent.score :name<otherStudent.name;  /*重载小于号,分数相同时,按name的字典序排序*/
	}
};             /*自定义结构体用于测试*/
template<typename T>
void selectionSort(T arr[],int n)
{
	for(int i=0;i<n-1;i++)
	{
		int minIndex=i;
		for(int j=i+1;j<n;j++)
		{
			if(arr[j]<arr[minIndex]){
				minIndex=j;
			}
		} 
		swap(arr[i],arr[minIndex]);
	}
}

int main()
{
   int a[10]={3,9,-1,4,0,8,68,-41,5,10};
   selectionSort(a,10);
   for(int i=0;i<10;i++)
       cout<<a[i]<<" ";	
	cout<<endl;
	
	float b[4]={4.4,3.5,6.7,-9.4};
	selectionSort(b,4);
	for(int i=0;i<4;i++)
		cout<<b[i]<<" ";
	cout<<endl;
	
	string c[4]={"A","D","B","E"};
	selectionSort(c,4);
	for(int i=0;i<4;i++)
		cout<<c[i]<<" ";
	cout<<endl;
	 
	Student d[4]={{"wm",90},{"zh",95},{"ly",100},{"hy",100}};
	selectionSort(d,4);
	for(int i=0;i<4;i++)
		cout<<d[i].name<<":"<<d[i].score<<" ";
	cout<<endl;
	 
	return 0;
} 

       以上共使用4个测试用例,包括自定义结构体进行测试。虽然结果简单明了,但是我们很容易发现在编写测试用例是非常繁琐,因此接下来将讲解如何随机生成测试用例:

首先,定义一个生成随机数的函数

int* generateRandomArray(int n,int rangeL,int rangeR)
{
	
	assert( rangeL<=rangeR);  /*assert宏的原型定义在<assert.h>中,其作用是如果他的条件返回错误,则终止程序执行,一般的还会出现提示对话,说明在什么地方引发了assert*/
	int * arr = new int[n];
	srand(time(NULL));       /*#include<ctime>,srand((unsigned)time(NULL))指使用系统定时/计时器的值作为随机种子*/
	for(int i=0;i<n;i++)
	{
		arr[i]=rand()%(rangeR-rangeL+1)+rangeL;
/*rand()函数不是真正的随机数生成器,而srand()会设置供rand()使用的随机数种子。如果你在第一次调用rand()之前没有调用srand(),那么系统会为你自动调用srand().*/
	}
	return arr;
}

由于主函数中每次打印数组输出时编写较为繁琐,我这里定义了一个打印函数。

template<typename T>
void printArray(T arr[],int n){
	for(int i=0;i<n;i++)
	    cout<<arr[i]<<' ';
	cout<<endl;
}

加入以上两个函数后,主函数测试一下:

int main()
{
   int a[10]={3,9,-1,4,0,8,68,-41,5,10};
    selectionSort(a,10);
    printArray(a,10);
	
	float b[4]={4.4,3.5,6.7,-9.4};
	selectionSort(b,4);
     printArray(b,4);
	
	string c[4]={"A","D","B","E"};
	selectionSort(c,4);
     printArray(c,4);
	 
	Student d[4]={{"wm",90},{"zh",95},{"ly",100},{"hy",100}};
	selectionSort(d,4);
	for(int i=0;i<4;i++)
		cout<<d[i].name<<":"<<d[i].score<<" ";
	cout<<endl;
	 
	 int m=50;
	 int *arr=generateRandomArray(m,0,m);
	 selectionSort(arr,m);
	 printArray(arr,m);
	 delete[] arr;
	return 0;
}
效果正如我们期望的那样。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值