一:选择排序
基本介绍
选择式排序也属于内部排序法,是从待排序的数据中,按照指定的规则选出某一元素,再依规定交换位置后达到排序的目的
选择排序思想:
选择排序(select sorting)也是一种简单的排序方法。
它的基本思想是:
第一次从arr[0]~
arr[n-1]中选取最小值,与arr[0]交换,
第二次从arr[1]~
arr[n-1]中选取最小值,与arr[1]交换,
第三次从arr[2]~
arr[n-1]中选取最小值,与arr[2]交换,…,
第i次从arr[i-1]~
arr[n-1]中选取最小值,与arr[i-1]交换,…,
第n-1次从arr[n-2]~arr[n-1]中选取最小值,与arr[n-2]交换,总共通过n-1次,得到一个按排序码从小到大排列的有序序列。
以上说总结一句话:就是说每次数组中挑选出最小的数,放在最前头,再从剩下的数组中挑选出最小的放在第二位,依次类推.
原始的数组:101,34,119,1
第一轮排序:1 34 119 101
第二轮排序:1,34,119,101
第三轮排序:1,34,101,119
说明:
- 选择排序一共有(数组大小-1)轮排序
- 每一轮排序又是一个循环,循环的规则(代码)
2.1 先假定当前的这个数是最小的.
2.2 然后和后面的每个数进行比较,如果发现有比当前数更小的数.就重新确定最小数.并得到下标
2.3 当遍历到数组的最后是,就得到本轮最小的数和下标
2.4 交换
选择排序的应用实例:
有一群牛,颜值分别是101,34,119,1请使用选择排序从低到高进行排序[101,34,119,1]
推导代码:
package com.qiu.sort;
import java.util.Arrays;
public class SelectSort {
public static void main(String[] args) {
int[] arr = {101,34,119,1};
selectSort(arr);
}
//选择排序
public static void selectSort(int[] arr){
//使用逐步推导的顺序
//第一轮原始的数组:101,34,119,1
//第一轮排序:1 34 119 101
//算法:先简单,再复杂
int minIndex = 0;
int min =arr[0];//假定这个数为零
for (int j = 0+1; j <arr.length ; j++) {
//这里的0+1,的意思就是说我们假定了这个数组的第一个数就是最小数,然后循环从第二个数开始
if (min>arr[j]){
//说明我们假定的最小值就不是最小的
min = arr[j];//重置最小值
minIndex = j;//重置最小值的索引
}
}
//将这个最小值放在arr[0]这个位置.即交换
//从上面循环代码来讲:扫描到的最小值的minIndex为3,这个minIndex为3
if (minIndex !=0){
arr[minIndex] = arr[0];//这里的arr[0]为101,这里就是说把101,放到之前扫描到那个最小的位置
arr[0] = min;//接着讲拿到的这个最小值,放在数组下边为0的这个位置
}
System.out.println("第一轮后");
System.out.println(Arrays.toString(arr));
//第一轮排序:1 34 119 101
//算法:先简单,再复杂
minIndex = 1;
min =arr[1];//假定这个数为零
for (int j = 1+1; j <arr.length ; j++) {
//这里的0+1,的意思就是说我们假定了这个数组的第一个数就是最小数,然后循环从第二个数开始
if (min>arr[j]){
//说明我们假定的最小值就不是最小的
min = arr[j];//重置最小值
minIndex = j;//重置最小值的索引
}
}
//将这个最小值放在arr[0]这个位置.即交换
//从上面循环代码来讲:扫描到的最小值的minIndex为3,这个minIndex为3
if (minIndex !=0){
arr[minIndex] = arr[1];//这里的arr[0]为101,这里就是说把101,放到之前扫描到那个最小的位置
arr[1] = min;//接着讲拿到的这个最小值,放在数组下边为0的这个位置
}
System.out.println("第二轮后");
System.out.println(Arrays.toString(arr));
//第一轮排序:1 34 119 101
//算法:先简单,再复杂
minIndex = 2;
min =arr[2];//假定这个数为零
for (int j = 2+1; j <arr.length ; j++) {
//这里的0+1,的意思就是说我们假定了这个数组的第一个数就是最小数,然后循环从第二个数开始
if (min>arr[j]){
//说明我们假定的最小值就不是最小的
min = arr[j];//重置最小值
minIndex = j;//重置最小值的索引
}
}
//将这个最小值放在arr[0]这个位置.即交换
//从上面循环代码来讲:扫描到的最小值的minIndex为3,这个minIndex为3
if (minIndex !=0){
arr[minIndex] = arr[2];//这里的arr[0]为101,这里就是说把101,放到之前扫描到那个最小的位置
arr[2] = min;//接着讲拿到的这个最小值,放在数组下边为0的这个位置
}
System.out.println("第三轮后");
System.out.println(Arrays.toString(arr));
}
}
代码调优:
package com.qiu.sort;
import java.util.Arrays;
public class SelectSort {
public static void main(String[] args) {
int[] arr = {101,34,119,1};
selectSort(arr);
}
//选择排序
public static void selectSort(int[] arr){
//使用逐步推导的顺序
//第一轮原始的数组:101,34,119,1
//第一轮排序:1 34 119 101
//算法:先简单,再复杂
//在推导的过程中,我们发现了规律,因此可以使用for循环来解决问题
for (int i = 0; i <arr.length-1 ; i++) {
int minIndex = i;
int min =arr[i];//假定这个数为零
for (int j = i+1; j <arr.length ; j++) {
//这里的0+1,的意思就是说我们假定了这个数组的第一个数就是最小数,然后循环从第二个数开始
if (min>arr[j]){
//说明我们假定的最小值就不是最小的
min = arr[j];//重置最小值
minIndex = j;//重置最小值的索引
}
}
//将这个最小值放在arr[0]这个位置.即交换
//从上面循环代码来讲:扫描到的最小值的minIndex为3,这个minIndex为3
if (minIndex !=i){
arr[minIndex] = arr[i];//这里的arr[0]为101,这里就是说把101,放到之前扫描到那个最小的位置
arr[i] = min;//接着讲拿到的这个最小值,放在数组下边为0的这个位置
}
System.out.println("第"+(i+1)+"轮后:");
System.out.println(Arrays.toString(arr));
}
}
}
代码运行显示:
同样的两个for循环.所以这里的时间负复杂度为O(n^2)
选择排序的速度测试:
同样的我们添加如下代码:
//测试一下冒泡排序的速度,给8w随机数组
int[] arr1 = new int[80000];
for (int i = 0; i < 80000; i++) {
arr1[i] =(int)(Math.random()*80000000);
}
//测试排序时间
Date date = new Date();
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateStr = format.format(date);
System.out.println("排序前的时间:"+dateStr);
selectSort(arr1);
Date date1 = new Date();
SimpleDateFormat format1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateStr1 = format1.format(date1);
System.out.println("排序前的时间:"+dateStr1);
得到的代码结果为:
可以看到这里排序的时间只有3秒,比冒泡排序快了很多.