排序基础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)

posted @ 2021-09-28 14:18  振袖秋枫问红叶  阅读(85)  评论(0)    收藏  举报