ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

简单排序大法

2021-08-01 09:33:17  阅读:226  来源: 互联网

标签:大法 min int 元素 Comparable 简单 排序 public


排序算法

说到排序,学过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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有