简介
(select sort)是一种简单直观的排序算法。它的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。 选择排序是不稳定的排序方法。
选择排序算法的运作如下:
- 首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。
- 再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。
- 重复第二步,直到所有元素均排序完毕。
视觉图效果
代码实现
public int[] selectSort(int[] nums){
int temp = 0;
int count=0, swapCount=0;
for (int i = 0; i < nums.length - 1; i++) {
// 认为目前的数就是最小的, 记录最小数的下标
int minIndex = i;
for (int j = i + 1; j < nums.length; j++) {
count ++;
if (nums[minIndex] > nums[j]) {
// 修改最小值的下标
minIndex = j;
}
}
// 当退出for就找到这次的最小值
if (i != minIndex) {
swapCount ++;
temp = nums[i];
nums[i] = nums[minIndex];
nums[minIndex] = temp;
}
}
System.out.println(count + " " + swapCount);
return nums;
}
测试
测试用例
- 数组长度1
- 数组长度10
- 数组长度100
- 数组长度1000
- 数组长度10000
- 数组长度100000
- 数组长度1000000
期望:数组长度越大,耗时越长,且呈现几何倍数递增
测试条件
硬件环境
配置项 | 配置值 |
---|---|
computer | MacBook Pro (Retina, 13-inch, Early 2015) |
graphics | Intel Iris Graphics 6100 1536 MB |
member | 16 GB 1867 MHz DDR3 |
processor | 3.1 GHz Dual-Core Intel Core i7 |
测试代码
public class AppTest{
App app = new App();
int[] one = new int[1];
int[] two = new int[10];
int[] three = new int[100];
int[] four = new int[1000];
int[] five = new int[10000];
int[] six = new int[100000];
@Before
public void before(){
one = generateRandomNumber(1);
two = generateRandomNumber(10);
three = generateRandomNumber(100);
four = generateRandomNumber(1000);
five = generateRandomNumber(10000);
six = generateRandomNumber(100000);
}
@Test
public void testDoItOne(){
System.out.print(1 + " ");
app.selectSort(one);
System.out.println("----------------");
}
@Test
public void testDoItTwo(){
System.out.print(2 + " ");
app.selectSort(two);
System.out.println("----------------");
}
@Test
public void testDoItThree(){
System.out.print(3 + " ");
app.selectSort(three);
System.out.println("----------------");
}
@Test
public void testDoItFour(){
System.out.print(4 + " ");
app.selectSort(four);
System.out.println("----------------");
}
@Test
public void testDoItFive(){
System.out.print(5 + " ");
app.selectSort(five);
System.out.println("----------------");
}
@Test
public void testDoItSix(){
System.out.print(6 + " ");
app.selectSort(six);
System.out.println("----------------");
}
// @Test
public void testDoItSeven(){
System.out.print(7 + " ");
int[] seven = generateRandomNumber(1000000);
long start = System.currentTimeMillis();
app.selectSort(seven);
long end = System.currentTimeMillis();
System.out.println("----------------");
System.out.println("耗时:"+ (end - start));
}
public static int[] generateRandomNumber(int length){
int[] randomArray = new int[length];
Random random = new Random();
for(int i=0;i<length;i++){
randomArray[i] = random.nextInt(length);
}
return randomArray;
}
}
测试结果
总结
T(1) = 长度1的数组排序耗时
毫秒级:T(1), T(10), T(100), T(1000) 10毫秒
秒级:T(10000) 50毫秒
十秒级:T(100000) 2.7秒
百秒级:T(1000000) 331秒
从上到下递增倍数是:5倍, 5倍, 100倍
分水岭是数组长度10000.
整个排序期间,并未创建多余的数组占用内存(除了几个用户辅助判断查找次数,交换次数的变量)
时间复杂度:O(logn*n)
空间复杂度:O(1)
从时间复杂度上看,选择排序性能明显优于> 鸡尾酒冒泡排序 > 冒泡排序