选择排序(Selection-Sort)
先把最小的拿出来
剩下的, 再把最小的拿出来
剩下的, 再把最小的拿出来
。。。
每次选择还没处理的元素里最小的元素
选择排序就是重复“从待排序的数据中寻找最小值,将其与序列最左边的数字进行交换”这一操作的算法。在序列中寻找最小值时使用的是线性查找。
比如: 对数字1~9进行排序。 使用线性查找在数据中寻找最小值,于是我们找到了最小值 1
先找到一个最小值索引
public class SelectionSort {
private SelectionSort(){};
public static void sort(int[] arr){
int minIndex=0;
for (int i = 0; i < arr.length; i++) {
if (arr[i] < arr[minIndex])
minIndex = i;
}
System.out.println(minIndex);
}
public static void main(String[] args) {
int[] arr = { 4, 2, 3, 6, 1, 5};
for(int e: arr)
System.out.print(e + " ");
System.out.println();
SelectionSort.sort(arr);
for(int e: arr)
System.out.print(e + " ");
}
}
无外层循环操作
public class SelectionSort0 {
private SelectionSort0(){};
public static void sort(int[] arr){
int minIndex=0;
for ( int j = 0; j < arr.length; j++) {
if (arr[j] < arr[minIndex])
minIndex =j;
}
System.out.println("minIndex = " + minIndex);
swap(arr, 0, minIndex);
for(int e: arr)
System.out.print(e + " ");
System.out.println();
System.out.println("----------------------");
minIndex=1;
for ( int j = 1; j < arr.length; j++) {
if (arr[j] < arr[minIndex])
minIndex =j;
}
System.out.println("minIndex = " + minIndex);
swap(arr, 1, minIndex);
for(int e: arr)
System.out.print(e + " ");
System.out.println();
System.out.println("----------------------");
minIndex=2;
for ( int j = 2; j < arr.length; j++) {
if (arr[j] < arr[minIndex])
minIndex =j;
}
System.out.println("minIndex = " + minIndex);
swap(arr, 2, minIndex);
for(int e: arr)
System.out.print(e + " ");
System.out.println();
System.out.println("----------------------");
}
private static void swap(int[] arr, int i, int minIndex){
int temp = arr[i]; arr[i] = arr[minIndex];arr[minIndex] = temp;
}
public static void main(String[] args) {
int[] arr = { 4, 3, 6, 1, 5, 2};
for(int e: arr)
System.out.print(e + " ");
System.out.println();
SelectionSort0.sort(arr);
// for(int e: arr)
// System.out.print(e + " ");
}
}
完整代码
public class SelectionSort {
private SelectionSort() {
}
;
public static void sort(int[] arr) {
for (int i = 0; i < arr.length; i++) {
int minIndex = i;
for (int j = i; j < arr.length; j++) {
if (arr[j] < arr[minIndex]) minIndex = j;
}
swap(arr, i, minIndex);
}
}
private static void swap(int[] arr, int i, int minIndex) {
int temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
public static void main(String[] args) {
int[] arr = {4, 3, 6, 1, 5, 2};
for (int e : arr)
System.out.print(e + " ");
System.out.println();
SelectionSort.sort(arr);
for (int e : arr)
System.out.print(e + " ");
}
}
选择排序使用了线性查找来寻找最小值,因此在第 1 轮中需要比较 n -1 个数字,第
2 轮需要比较 n -2 个数字……到第 n -1 轮的时候就只需比较 1 个数字了。因此,总的比
较次数与冒泡排序的相同,都是 (n-1)+(n-2)+…+1 ≈ n2/2 次。每轮中交换数字的次数最多为 1 次。如果输入数据就是按从小到大的顺序排列的,便不需要进行任何交换。选择排序的时间复杂度为 O(n2)。
复杂度分析
表示算法的性能
常见算法复杂度分析
- 线性查找法 —> O (n)
- 一个数组中元素可以组成那些数据对 —> O (n^2)
- 遍历二维数组 —> O (n^2)
- log(n)
举例: 二分搜索
在最好情况下二分搜索的时间复杂度是 O(1),最坏情况(平均情况)下 O(log n),我们直接来看最坏情况下的例子。已知有 16 个元素的有序数组。
举个最坏情况的例子,比如我们要找的是数字 13。
选中间的元素作为中心点(长度的一半)
13 小于中心点,所以不用考虑数组的后一半
重复这个过程,每次都寻找子数组的中间元素
每次和中间元素比较都会使搜索范围减半。
所以为了从 16 个元素中找到目标元素,我们需要把数组平均分割 4 次,也就是说,
-
求约数 — 》O (n)
-
根号O ( n)
-
长度为 n的二进制数字 O(2^n)
-
长度为 n的数组的所有排列 O(n!)
-
判断数字是否为偶数 O(1)
复杂度计较
O(1) < O(logn) < O(根号n) < O(n) < O(nlogn)< O(n^2) < O(2^n) < O(n!)
空间复杂度和时间复杂度同理
更改代码为泛型支持
在Java中的类比较必须实现 Comparable接口
编写实现 Comparable接口的实体类Student
import java.util.Objects;
/**
* @ Author :Eric Lee
* @ Date :Created in 11:35 2021/8/14
* @ Description:
* @ Modified By:
* @ Version : 1.0
*/
public class Student implements Comparable<Student> {
private String name;
private Integer score;
private Double height;
public Student() {
}
public Student(String name, Integer score, Double height) {
this.name = name;
this.score = score;
this.height = height;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getScore() {
return score;
}
public void setScore(Integer score) {
this.score = score;
}
public Double getHeight() {
return height;
}
public void setHeight(Double height) {
this.height = height;
}
@Override
public String toString() {
return "Student{" + "name='" + name + '\'' + ", score=" + score + ", height=" + height + '}';
}
@Override
public int compareTo(Student o) {
// 分数比较
// if (this.score < o.score)
// return -1;
// else if (this.score == o.score)
// return 0;
// return 1;
// return this.score - o.score; //升序
return o.score - this.score ; //降序
}
}
更改为泛型支持并测试
/**
* @ Author :Eric Lee
* @ Date :Created in 11:37 2021/8/14
* @ Description:
* @ Modified By:
* @ Version : 1.0
*/
public class SelectionSort {
private SelectionSort() {
}
public static <E extends Comparable<E>> void sort(E[] arr) {
for (int i = 0; i < arr.length; i++) {
int minIndex = i;
for (int j = i; j < arr.length; j++) {
// j 位置 - minIndex 位置 小于0 证明j位置更小
if (arr[j].compareTo(arr[minIndex]) < 0)
minIndex = j;
}
swap(arr, i, minIndex);
}
}
private static <E> void swap(E[] arr, int i, int minIndex) {
E temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
public static void main(String[] args) {
Student[] students = data();
for (Student s: students) {
System.out.println(s);
}
System.out.println("---------------------------------");
SelectionSort.sort(students);
for (Student s: students) {
System.out.println(s);
}
}
public static Student[] data(){
Student s1 = new Student("张三", 23, 1.6);
Student s2 = new Student("李思", 43, 1.9);
Student s3 = new Student("王五", 12, 1.4);
Student s4 = new Student("赵六", 11, 1.5);
Student s5 = new Student("田七", 52, 1.8);
Student[] stus = new Student[5];
stus[0] = s1;
stus[1] = s2;
stus[2] = s3;
stus[3] = s4;
stus[4] = s5;
return stus;
}
}