其他分享
首页 > 其他分享> > 简单排序大法

简单排序大法

作者:互联网

排序算法

说到排序,学过Java的人肯定第一时间相当Comparable接口,接下来就和大家一起以熟悉的方式来学习排序。

Comparable接口

用来定义排序规则的接口
实际应用场景中更多的是对对象进行排序,这就需要对象实现该接口,并自定义排序规则。

/**用户类*/
public class User implements Comparable<User>{
    public static void main(String[] args) {
        User admin = new User(10, "admin", 100);
        User root = new User(2, "root", 99);
        int i = admin.compareTo(root);
        System.out.println(i);
        System.out.println();
    }
    private int id;
    private String username;
    private int age;

    public User() {
    }

    public User(int id, String username, int age) {
        this.id = id;
        this.username = username;
        this.age = age;
    }

    //实现Comparable接口,传入要比较的泛型。实现排序方法
    @Override
    public int compareTo(User o) {
        //设置排序规则。以id为排序原则
        return this.id-o.id;
    }
}

学习思路时根据算法思想进行理解和实现。

数学公式

摆一些数学公式,防止刚开始被劝退。
等差数列求和公式:Sn=a1*n+ [n* (n-1)*d]/2或Sn= [n* (a1+an)]/2

简单排序

冒泡排序、选择排序、插入排序。
适用于少量数据的情况。
注:所提供代码API本着代码规范,都进行了最小划分
1.排序
2.比较数组两个元素
3.交换数组两个元素

1.冒泡排序

思想:

  1. 比较相邻的元素。如果前一个元素比后一个元素大,就交换这两个元素的位置。
  2. 对每一对相邻元素做同样的工作,从开始第一对元素到结尾的最后一对元素。最终最后位置的元素就是最大
    值。
    实现:通过转载的图来理解下边的代码
    在这里插入图片描述
package yh.com.logstash.simpleSort;

import java.util.Arrays;
/**冒泡排序:按照main中的思路去;理解,秒懂!!!
 * 安排一波:
 *      等差数列求和公式:Sn=a1*n+ [n* (n-1)*d]/2或Sn= [n* (a1+an)]/2
 *       防止刚来被劝退的情况发生,苦笑!*/
public class Bubble {
    public static void main(String[] args) {
        Integer[] a={9,3,6,1,7,2,8,5};
        sort1(a);
        System.out.println(Arrays.toString(a));
        System.out.println(a.length);
        sort2(a);
        System.out.println(Arrays.toString(a));
        sort(a);
        System.out.println(Arrays.toString(a));
    }
    /**
     * 对数组内的元素进行排序
     */
    public static void sort1(Comparable[] a) {
        /**冒泡1.0:
         *      完成一次冒泡排序*/
        for (int i = 0; i < a.length-1; i++) {
            if (greater(a[i], a[i + 1])) {
                exchange(a, i, i + 1);
            }
        }
    }
    public static void sort2(Comparable[] a) {
        /**冒泡1.1:
         *      完成第二次冒泡排序*/
        for (int i = 0; i < a.length-2; i++) {
            if (greater(a[i], a[i + 1])) {
                exchange(a, i, i + 1);
            }
        }
    }

    public static void sort(Comparable[] a) {
        /**冒泡2.0:
         *      突然明悟,由1.0控制每轮的比较和交换
         *              由2.0中外层循环控制每次参加排序的个数
         *                  第一次参加的排序的个数为数组的总数,
         *                  第二次则减去1,最后一个已为最大。
         *                  i的边界值为>1是因为剩下一个元素则不需要比较直接为最小啦*/
        for (int i=a.length;i>1;i--){
            for (int j=0;j<i-1;j++){
                if (greater(a[j],a[j+1])){//比较次数:n-1+n-2+...+1=n^2/2-n/2
                    exchange(a,j,j+1);//交换次数:n-1+n-2+...+1==n^2/2-n/2
                }
            }
        }
        //总结:时间复杂度为:比较次数+交换次数=n^2-n
    }

    /**
     * 比较讲个元素大小
     */
    private static boolean greater(Comparable x, Comparable y) {
        return x.compareTo(y) > 0;
    }

    /**
     * 交换数组中两个元素位置
     */
    private static void exchange(Comparable[] a, int i, int j) {
        Comparable tamp;
        tamp = a[i];
        a[i] = a[j];
        a[j] = tamp;
    }
}

2.选择排序

思想:

  1. 每一次遍历的过程中,都假定第一个索引处的元素是最小值,和其他索引处的值依次进行比较,如果当前索引处的值大于其他某个索引处的值,则假定其他某个索引出的值为最小值,最后可以找到最小值所在的索引
  2. 交换第一个索引处和最小值所在的索引处的值
  3. 将定义最小值索引递增后重复1,2
    实现:通过转载的图来理解下边的代码
    在这里插入图片描述
package yh.com.logstash.simpleSort;

import java.util.Arrays;

/**
 * 选择排序:
 */
public class Selection {
    public static void main(String[] args) {
        Integer[] a = {3, 9, 6, 1, 7, 2, 8, 5};
        sort1(a);
        System.out.println(Arrays.toString(a));
        sort2(a);
        System.out.println(Arrays.toString(a));
        sort(a);
        System.out.println(Arrays.toString(a));

    }

    /**
     * 对数组内的元素进行排序
     */
    public static void sort1(Comparable[] a) {
        /**选择1.0:
         *      让a[0]处的值为最小min,和后边的所有值比较,有更小的则更改min的值*/
        int min = 0;
        for (int i = min+1; i < a.length - 1; i++) {
            //拿min处的值依次和后边的所有进行比较,大则
            if (greater(a[min], a[i])) {
                min = i;
            }
        }
        exchange(a, min, 0);
        System.out.println(min);
        //
    }

    public static void sort2(Comparable[] a) {
        /**选择1.1
        *      让a[1]处的值为最小min,和后边的所有值比较,有更小的则更改min的值*/
        int min = 1;
        for (int i = min+1; i < a.length - 1; i++) {
            if (greater(a[min], a[i])) {
                min = i;
            }
        }
        exchange(a, min, 1);
        System.out.println(min);
    }

    public static void sort(Comparable[] a) {
        /**选择2.0
         *      外层循环控制要设置为min的值
         *      内层循环控制和min值往后所有的值的比较*/
        for (int i=0;i<a.length-1;i++){
            int min=i;
            for (int j=i+1;j<a.length;j++){//最后一轮比较要比较最后一个值,故边界为<a.length
                if (greater(a[min],a[j])){//比较次数:n-1+n-2+...+2+1=n^2/2-n/2
                    min=j;
                }
            }
            //循环执型完成后已找到最小值的索引值,只需要交换一次即可
            exchange(a,min,i);//数据交换次数:n-1
        }
        //总结:时间复杂度=比较次数+交换次数=n^2/2+n^2-1
        //省略常数项,低次项,最高此项的常数后,时间复杂度为O(n^2)
    }

    /**
     * 比较讲个元素大小
     */
    private static boolean greater(Comparable x, Comparable y) {
        return x.compareTo(y) > 0;
    }

    /**
     * 交换数组中两个元素位置
     */
    private static void exchange(Comparable[] a, int i, int j) {
        Comparable tamp;
        tamp = a[i];
        a[i] = a[j];
        a[j] = tamp;
    }
}

3.插入排序

思想:

  1. 把所有的元素分为两组,已经排序的和未排序的;初始时默认下标0处为已排序
  2. 找到未排序的组中的第一个元素,向已经排序的组中进行插入;
  3. 倒叙遍历已经排序的元素,依次和待插入的元素进行比较,当待插入元素小于倒序元素时,两者交换。否则退出遍历(因为已排序数组最后一个值小于等于带插入元素时,已为有序不需要交换)
    注意:理解思想时的坑,带插入元素满足条件时会交换,莫要掉坑!!!!
    实现:通过下图来理解下边的代码
    在这里插入图片描述
package yh.com.logstash.simpleSort;
import java.util.Arrays;
/**
 * 插入排序:
 */
public class Insertion {
    public static void main(String[] args) {
        Integer[] a = {3, 9, 6, 1, 7, 2, 8, 5};
        //正确算法
        sort(a);
        System.out.println(Arrays.toString(a));
        //错误演示
        sort1(a);
        System.out.println(Arrays.toString(a));
    }
    /**
     * 对数组内的元素进行排序
     */
    public static void sort(Comparable[] a) {
        /**插入1.0:
         *      外层循环用于控制待插入元素。默认起始已排序数组只有a[0]
         *      内存循环用来倒叙遍历已排序数组,其长度为外层循环待插入值的下标
         *      交换条件是当在已排序数组中找到一个值大于代插入值时,两者交换。
         *      然后继续向前遍历已排序数组。
         *      未找到则直接退出内层循环,直接进行下一个待插入元素的插入。*/
        for (int i = 1; i < a.length; i++) {
            //当前元素为a[i],依次和i前面的元素比较,找到一个小于等于a[i]的元素则交换
            for (int j = i; j > 0; j--) {
                //拿已排好序的数组和代插入元素比较。满足则交换。依次向前两两比较,有则交换,无则不用再继续往前执行退出即可
                /**注意:这块可能拿a[j]来做比较大家不好理解。
                 *      可以想象一下,当拿a[i]比较时,第一次满足if后进行交换,
                 *      继续执行第二次,会发现参与比较的还是a[i],实际上应当是a[j-1]和a[j]
                 *举例:初始数组:{3, 9, 6, 1, 7, 2, 8, 5};
                 *      已排序数组为前5个即{1,3,6,7,9}
                 *      当下标i=5时,
                 *          内层循第一次比较的是a[4]和a[5],即9和2.满足条件两者交换
                 *          第二次应当比较的是2和7才是,如果拿a[i]和a[3]参与比较,则是拿交换后的9和7进行比较,会走到else
                 *          导致跳出循环,最终数组变为{1,3,6,7,2,9}*/
                if (greater(a[j - 1], a[j])) {//比较次数:1+2+3+...+n-1=n^2/2-n/2
                    exchange(a, j, j - 1);//交换次数为:1+2+...+n-1=n^2/2-n/2
                    System.out.println(Arrays.toString(a));
                } else {
                    break;
                }
            }
        }
        //总结:时间复杂度=比较次数+交换次数=n^2-n,即O(n^2)
    }

    public static void sort1(Comparable[] a) {
        for (int i = 1; i < a.length; i++) {
            //当前元素为a[i],依次和i前面的元素比较,找到一个小于等于a[i]的元素则交换
            for (int j = i; j > 0; j--) {
                //错误示范,当拿a[i]参与if中的比较时
                if (greater(a[j - 1], a[i])) {
                    exchange(a, i, j - 1);
                    //观察第六行输出,即i=5时排序后的结果
                    System.out.println(Arrays.toString(a));//[1, 3, 6, 7, 2, 9, 8, 5]
                } else {
                    break;
                }
            }
        }
    }
    /**
     * 比较讲个元素大小
     */
    private static boolean greater(Comparable x, Comparable y) {
        return x.compareTo(y) > 0;
    }
    /**
     * 交换数组中两个元素位置
     */
    private static void exchange(Comparable[] a, int i, int j) {
        Comparable tamp;
        tamp = a[i];
        a[i] = a[j];
        a[j] = tamp;
    }
}

至此简单排序学习完毕,发现时间复杂度都为O(n^2),只适合小量数据场景。

这就需要我们学习更为高级的排序。

标签:大法,min,int,元素,Comparable,简单,排序,public
来源: https://blog.csdn.net/weixin_45466462/article/details/119215359