排序基础01:选择排序法
核心思想:从第一个元素开始,从前往后进行遍历,将找到的最小元素放在第一位;然后从第二位元素开始,继续找出剩下元素中的最小值,放在第二位...最终完成排序
实现选择排序法
使用泛型约束并实现Comparable接口
Comparable 是排序接口
若一个类实现了Comparable接口,就意味着“该类支持排序”,可以通过 Collections.sort(或 Arrays.sort)进行排序
实现Comparable接口的类的对象可以用作“有序映射(如TreeMap)”中的键或“有序集合(TreeSet)”中的元素,而不需要指定比较器
Comparable 接口仅仅只包括一个方法compareTo()
import java.util.Arrays;
public class Algorithm {
public static void main(String[] args) {
Integer[] arr = {6, 4, 2, 3, 1, 5};
SelectionSort.sort(arr);
String[] str = {"erhg", "afhbgjg", "fjfg", "hfhfuhu"};
SelectionSort.sort(str);
System.out.println(Arrays.toString(arr));
System.out.println(Arrays.toString(str));
}
}
class SelectionSort {
private SelectionSort(){}
/**
* 泛型实现Comparable接口约束,就可以用compareTo()方法对任意类型进行比较排序,注意泛型实现接口或继承类只能使用extends关键字
*/
public static<E extends Comparable<E>> void sort(E[] arr){
for (int i = 0; i < arr.length - 1; i++) {
/**
* 循环不变量:arr[i...n)未排序,而arr[0...i)已排序
* 找到arr[i...n)中最小值的索引,然后将这个最小值和arr[i]互换位置
*/
int minIndex = i;
for (int j = i + 1; j < arr.length; j++) {
/**
* A.compareTo(B),如果A > B返回正数;A < B返回负数
*/
if (arr[j].compareTo(arr[minIndex]) < 0) {
minIndex = j;
}
}
/**
* 优化点:如果最小索引没变,就不用互换
*/
if (i != minIndex) {
E tem;
tem = arr[minIndex];
arr[minIndex] = arr[i];
arr[i] = tem;
}
}
}
}
拓展:Comparator 是比较器接口
可以通过“实现Comparator类来新建一个比较器”,然后通过该比较器对类进行自定义排序
对自定义类排序,该类要实现Comparable接口,重写compareTo()方法
public class Algorithm {
public static void main(String[] args) {
Student[] student = {new Student("Alice", 98),
new Student("Bob", 100),
new Student("Cindy", 66)};
SelectionSort.sort(student);
for (Student stu : student) {
System.out.print(stu + " ");
}
}
}
class SelectionSort {
private SelectionSort(){}
public static<E extends Comparable<E>> void sort(E[] arr){
for (int i = 0; i < arr.length - 1; i++) {
int minIndex = i;
for (int j = i + 1; j < arr.length; j++) {
if (arr[j].compareTo(arr[minIndex]) < 0) {
minIndex = j;
}
}
if (i != minIndex) {
E tem;
tem = arr[minIndex];
arr[minIndex] = arr[i];
arr[i] = tem;
}
}
}
}
/**
* Student类实现Comparable接口,重写compareTo()方法
*/
class Student implements Comparable {
private String name;
private int score;
public Student(String name, int score){
this.name = name;
this.score = score;
}
/**
* 重写compareTo()方法,指定通过score属性来比较大小
* compareTo()方法传入的参数会被转成Object类型,具体比较的时候需要强制转换一下
*/
@Override
public int compareTo(Object o) {
Student stu = (Student) o;
return this.score - stu.score;
}
@Override
public String toString() {
/**
* String.format()方法格式化打印
*/
return String.format("Student(name: %s, socre: %d)", name, score);
}
}
复杂度分析
选择排序法的时间复杂度为O(n^2)