之前在我的博文中详细介绍了冒泡排序,它的基本思想是:每次比较相邻两个数的大小,只要逆序(和题意要求的顺序相反),就交换两个数;这样交换的次数繁多!而选择排序法就避免了这个问题。
选择排序的基本思想:
找到当前数字序列中最大(最小)的数,记录其所在位置,将其和最前面(最后面)的数进行交换,使最小(最大)的元素上浮(下沉)到本次排序的最前面(最后面),从而完成一趟(pass)排序。下一趟排序时,已经有序的元素不再参与。这样的话,n个元素需要进行n-1趟排序!!!
举个例子:4个数字4,6,7,5进行从大到小的排序。
第一趟:参与数字序列:4,6,7,5
找到该数字序列中最大的数7,记录其所在位置,将其和第一个位置的数4进行比较,7大于4,所以7和4交换,得到新的序列(7),6,4,5
经过第一趟的排序,使数字序列中最大的数7上浮到最前面,此时7属于有序的元素,不需要参与到下一趟的排序。
第二趟排序:参与数字序列:6,4,5
找到该数字序列中最大的数6,记录其所在位置,将其和第一个位置的数6进行比较,6等于6,不需要交换,得到新的序列(7,6),4,5
经过第二趟的排序,使数字序列中第二大的数6上浮到第二个前面,此时7,6属于有序的元素,不需要参与到下一趟的排序。
第三趟排序:参与数字序列4,5
找到该数字序列中最大的数5,记录其所在位置,将其和第一个位置的数4进行比较,5大于4,所以5和4交换,得到新的序列(7,6,5),4
经过第三趟的排序,使数字序列中第三大的数5上浮到第三个前面,此时7,6,5属于有序的元素,不需要参与到下一趟的排序。
最后就剩下一个数4,就不需要进行排序,排序最终得到的数字序列为:7,6,5,4;
当然也可以选择最小的数下沉到最后面,学者可以自己模拟一下排序过程!!
选择排序的关键点:
(1)采用双层循环:时间复杂度也是O(n的平方)
外层循环表示的是排序的趟数,n个数字需要n-1趟,因此,外层循环的次数是n-1次;同时也代表数的位置。
内层循环表示的是每一趟排序的数字。根据选择排序的思想,第i趟排序时,最前面的位置就是i,用一个循环来不断更新。
(2)找到最值数的位置,将该位置的数和当前序列最前面(最后面)位置的数进行交换;。(稳定排序)
如果有什么问题,可以向我提问。更多知识,可以关注我,也可以加入我的知识星球,袁君和他的朋友们,更多的人在这里学习!有算法学习、理财、生活、职场等多方面的知识!
如果还有什么问题,可以向我提问。这里,也附上完整的选择排序的C++代码和相关注释;
#include<iostream>
using namespace std;
#define N 5
int main() {
int a[N],pos;
int i,j,temp;
printf("Please input %d numbers:\n",N);
for(i=0; i<N; i++)
scanf("%d", &a[i]);
/*冒泡排序的核心代码*/
/*方式一:找到最大的数,实现从大到小的排序*/
for(i=0; i<N-1; i++) { //外层循环表示排序的趟数,N个数总共进行N-1趟排序
pos=i;//存储最值的位置
for(j=i+1; j<N; j++) { //内层循环表示每一趟参与排序的数字
if(a[j]>a[pos]) {//找到当前序列中最大数字所在的位置
pos=j;
}
}
if(pos!=i){//当找到的最大数字的位置发生变化的时候,才交换两个数的位置
temp=a[pos]; //把最大的数放在当前序列的最前面。
a[pos]=a[i];
a[i]=temp;
}
}
printf("\nthe result of sort:\n");
for(i=0; i<N; i++)
printf("%d ",a[i]);
}