原理
多次遍历,依次选出每次的最大/小项进行排列。
实现
这是传统的选择排序,不使用格外内存,就地交换值进行排序。
void algorithm(void)
{
int i,j,buffer,minIndex,min;
for(i = 0;i < DATA_AMOUNT - 1;i++)
{
min = INT_MAX;
for(j = i;j < DATA_AMOUNT;j++)
{
if(nums[j] < min)
{
min = nums[j];
minIndex = j;
}
}
//swap
buffer = nums[i];
nums[i] = min;
nums[minIndex] = buffer;
}
}
完整代码
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <time.h>
#include <limits.h>
#define DATA_AMOUNT 50000
#define ALGORITHM_NAME "不使用格外内存的选择排序"
int nums[DATA_AMOUNT];
void algorithm(void);
int main(void)
{
for(int i = 0;i < DATA_AMOUNT;i++) nums[i] = rand()%10001;//(0,10000)
int start,end;
start = clock();
algorithm();
end = clock();
printf("algorithm \"%s\" used %f sec to process %d data\n",ALGORITHM_NAME,(float)(end - start)/CLOCKS_PER_SEC,DATA_AMOUNT);
for(int i = 0;i < DATA_AMOUNT - 1;i++)
{
if(nums[i] > nums[i+1])
{
puts("FAILED");
abort();
}
}
puts("PASSED");
return 0;
}
void algorithm(void)
{
int i,j,buffer,minIndex,min;
for(i = 0;i < DATA_AMOUNT - 1;i++)
{
min = INT_MAX;
for(j = i;j < DATA_AMOUNT;j++)
{
if(nums[j] < min)
{
min = nums[j];
minIndex = j;
}
}
//swap
buffer = nums[i];
nums[i] = min;
nums[minIndex] = buffer;
}
}
三次测试结果
第一次 | 第二次 | 第三次 | 平均 |
---|---|---|---|
0.755189 sec | 0.693200 sec | 0.693922 sec | 0.714104 sec |
性能和稳定性
-
先说结论:比冒泡快,不稳定。
-
选择排序的时间复杂度和冒泡排序一样为 O ( n 2 ) O(n^2) O(n2),但交换次数比冒泡排序少,所以效率更高。
-
选择排序是不稳定的,这一点主要体现在无法区分相同值的前后顺序,例如有一序列:{5,8,5,2,9},选择排序无法保证两个5在排序后依然按照之前的顺序排列。