排序算法(不断补充)

一.冒泡排序

package 冒泡排序;

import java.util.Arrays;

/**
 * @author 2902996750
 * @version 1.0
 * @date 2022/10/5 10:50
 * 实现冒泡排序: 冒泡排序循环一遍最大值就跑到最后面
 * 冒泡排序原理:
 *     1.比较相邻的元素,如果前一个元素比后一个元素大,就交换这两个位置
 *     2.对每一对相邻元素做同样的工作,从开始第一对元素到结尾的最后一对元素,最终最后位置的元素就是最大值
 * 实现过程:
 *     1.首先需要考虑到一次循环最多需要比较几回,确定j的范围。
 *       例如:5个数据,从下标0开始,只需要比较01,12,23,34,只需要比较四回
 *     2.然后确定循环的次数,因为是从下标0开始,所以需要 length-1,同时只需要循环length-1-1遍就可以了。
 */
public class TestMaoPao {
    public static void main(String[] args) {
        int[] arg={5,3,7,5,9,8,2,4,1,6,0};
        for (int i = arg.length-1; i>0; i--) {
            for (int j = 0; j < i; j++) {
                if (ToComparable.compare(arg,j,j+1)){
                    ToComparable.exchange(arg,j,j+1);
                }
            }
        }
        System.out.println(Arrays.toString(arg));
    }
}
package 冒泡排序;

/**
 * @author 2902996750
 * @version 1.0
 * @date 2022/10/5 11:17
 * ToComparable类:存放排序所需要的比较方法
 */
public class ToComparable {

    /**
     * 比较方法,返回大的对象
     * @param a 对象a
     * @param b 对象b
     * @return 最大的值
     */
    public static boolean compare(int[] arg,int a, int b){
        return arg[a]-arg[b]>0;
    }

    /**
     * 交换两个元素的位置
     */
    public static void exchange(int[] arg,int a,int b){
        int c;
        c=arg[b];
        arg[b]=arg[a];
        arg[a]=c;
    }
}

二.选择排序

package 选择排序;

import java.util.Arrays;

/**
 * @author 2902996750
 * @version 1.0
 * @date 2022/10/5 12:06
 * 实现选择排序: 每次循环都保证第一个索引处的元素是最小的。
 * 选择排序原理:
 *     1.每一次遍历的过程中,都假定第一个索引处的元素是最小值,和其他索引处的元素进行比较,
 *     2.如果当前索引的值大于比较的索引的值,那么进行交换位置。
 * 实现过程:
 *     1.因为一直需要拿前面的索引和后面的每一个索引对应的值比较,所以 j<=length-1。
 *     2.因为是从下标0开始,所以需要循环的次数需要是length-1-1,
 *       例如:5个长度的数组,需要遍历4次就行,但因为从0开始,所以只要满足条件 i<length-1 就可以了。
 */
public class TestXuZe {
    public static void main(String[] args) {
        int[] arg={5,3,7,5,9,8,2,4,1,6,0};
        for (int i = 0; i < arg.length-1; i++) {
            for (int j = i+1; j <= arg.length-1; j++) {
                if (ToComparable.compare(arg,i,j)){
                    ToComparable.exchange(arg,i,j);
                }
            }
        }
        System.out.println(Arrays.toString(arg));
    }
}
package 选择排序;

/**
 * @author 2902996750
 * @version 1.0
 * @date 2022/10/5 11:17
 * ToComparable类:存放排序所需要的比较方法
 */
public class ToComparable {

    /**
     * 比较方法,返回大的对象
     * @param a 对象a
     * @param b 对象b
     * @return 最大的值
     */
    public static boolean compare(int[] arg,int a, int b){
        return arg[a]-arg[b]>0;
    }

    /**
     * 交换两个元素的位置
     */
    public static void exchange(int[] arg,int a,int b){
        int c;
        c=arg[b];
        arg[b]=arg[a];
        arg[a]=c;
    }
}

三.插入排序

package 插入排序;

import java.util.Arrays;

/**
 * @author 2902996750
 * @version 1.0
 * @date 2022/10/5 12:30
 * 实现插入排序:
 * 插入排序原理:
 *     1.把所有元素分成两组,已经排序的和未排序的
 *     2.找到未排序的组中的第一个元素,向已经排序的组中进行插入
 *     3.倒叙遍历已经排序的元素,依次和待插入元素比较,直到找到一个元素小于待插入元素,
 *       那么把待插入元素放到一个位置,其他的元素往后移动一位
 * 实现过程:
 *     1.首先需要获得未插入元素的第一个元素,又因为数组第一个元素不需要比较,所以 i 从下标1开始。
 *     2.因为需要拿未插入元素与已插入元素倒着比较,所以 j=i ,
 *       又因为 j 与 j-1 比较,所以j不能为0,否则会抛出数组越界异常。
 */
public class TestChaRu {
    public static void main(String[] args) {
        int[] arg={5,3,7,5,9,8,2,4,1,6,0};
        //最外层循环相当于拿到未插入元素组的第一个元素
        for (int i = 1; i < arg.length; i++) {
            //第二层循环相当于拿未插入元素与它前面的元素进行冒泡排序
            for (int j = i; j>0 ; j--) {
                //如果未插入元素比离它最近的已插入元素大,那么结束当前内循环
                if (ToComparable.compare(arg,j,j-1)){
                   break;
                }else {
                    //否则,就进行互相交换。
                    //然后下次循环就拿互换完位置处的元素与它的前一个元素比较(倒着和已插入元素比较)。
                    ToComparable.exchange(arg,j,j-1);
                }
            }
        }
        System.out.println(Arrays.toString(arg));
    }
}
package 插入排序;

/**
 * @author 2902996750
 * @version 1.0
 * @date 2022/10/5 11:17
 * ToComparable类:存放排序所需要的比较方法
 */
public class ToComparable {

    /**
     * 比较方法,返回大的对象
     * @param a 对象a
     * @param b 对象b
     * @return 最大的值
     */
    public static boolean compare(int[] arg,int a, int b){
        return arg[a]-arg[b]>0;
    }

    /**
     * 交换两个元素的位置
     */
    public static void exchange(int[] arg,int a,int b){
        int c;
        c=arg[b];
        arg[b]=arg[a];
        arg[a]=c;
    }
}

四.希尔排序------高级排序

package 希尔排序;

import java.util.Arrays;

/**
 * @author 2902996750
 * @version 1.0
 * @date 2022/10/5 16:43
 * 实现希尔排序:
 *     1.本质上就是个加强版的插入排序,只不过原来的插入排序是相当于h=1的时候的情况
 *     2.插入排序是把索引为0的看成第一次已经分好的组,后面的都是未分好的组
 *       它让未分好的组的元素不断与前面元素就行比较,然后不断就行循环
 *     3.希尔排序是把从h开始的划分为未分好的组,h前面的是分好的组
 *       它让未分好的组的元素a,与a对应索引 - 增长量h(n>=1)所对应的元素就行比较,然后不断就行循环。
 * 希尔排序原理:
 *     1.选定一个增长量h,按照增长量h作为数据分组的依据,对数据进行分组。
 *     2.对分好组的每一组数据完成插入排序。
 *     3.减小增长量,最小减为1,,重复第二次操作
 * 实现过程:
 *     1.首先需要确定一个增长量 h 来进行分组
 *     2.然后索引从 h 之后都是属于未分好组的。
 *     3.因为需要使用插入排序,用未排序的第一个来与前面分好组的元素进行比较,所以 i = h
 *       对于第二层循环使用 h 而不像插入排序使用 0 是因为怕发生数组越界。
 *       例如: 3 已经是h对应的最靠前的元素索引,但条件用j>0,就会进行再一次 -h 操作,此时就会发生 j <0
 *     4.因为 h 是>=1 的,并且需要与下标索引=0比较,所以 j>=1 (如果没有等于1,那么当 h=1 时,就会出现索引 1 不会与索引 0 进行比较)
 */
public class TestXiEr {
    public static void main(String[] args) {
        int[] arg={5,3,7,5,9,8,2,4,1,6,0};
        //确定第一次循环的增长量 h
        int h=1;
        while (h < arg.length){
            h=2*h+1;
        }
        //开始希尔排序,满足h>=1才进行排序,小于就不排序了
        while (h>=1){
            //最外层循环确定未分好组的元素
            for (int i = h; i < arg.length; i++) {
                //这层循环用于与分好组的对象进行比较
                for (int j = i; j >=h; j=j-h) {
                    if (ToComparable.compare(arg,j,j-h)){
                        break;
                    }else {
                        ToComparable.exchange(arg,j,j-h);
                    }
                }
            }
            //执行完确定下一次的增长量 h
            h=h/2;
        }
        System.out.println(Arrays.toString(arg));
    }
}
package 希尔排序;

/**
 * @author 2902996750
 * @version 1.0
 * @date 2022/10/5 11:17
 * ToComparable类:存放排序所需要的比较方法
 */
public class ToComparable {

    /**
     * 比较方法,返回大的对象
     * @param a 对象a
     * @param b 对象b
     * @return 最大的值
     */
    public static boolean compare(int[] arg,int a, int b){
        return arg[a]-arg[b]>0;
    }

    /**
     * 交换两个元素的位置
     */
    public static void exchange(int[] arg,int a,int b){
        int c;
        c=arg[b];
        arg[b]=arg[a];
        arg[a]=c;
    }
}

五.归并排序------高级排序

package 归并排序;

import java.util.Arrays;

/**
 * @author 2902996750
 * @version 1.0
 * @date 2022/10/5 20:29
 * 实现归并排序:就是将两个组(实际上就是两个连续区间)的值比较完的值放到一个新的对象中,最后将新组内容赋值给原来数组对应位置处
 * 归并排序原理:
 *     1.尽可能的将一组数据分成两个元素相等的子组,并对每一个子组继续拆分,直到拆分后的每个子组的元素个数是1为止
 *     2.将相邻的两个子组进行合并成一个有序的大组
 *     3.不断的重复步骤2,直到最终只有一个组为止
 * 实现过程:
 *     1.分组:就是获取到对应范围的值
 *     2.合并:就是通过new一个新数组,将比较完对应最小的值放到新数组对应位置,最后再讲新数组的值赋值给原来的数组
 *       往新数组放值,要考虑三种情况;'两个指针一起移动完','p1移动完p2没移动完','p1没移动完p2移动完'
 */
public class TestGuiBing {
    public static void main(String[] args) {
        int[] arg={5,3,7,5,9,8,2,4,1,6,0};
        ToComparable.sort(arg);
        System.out.println(Arrays.toString(arg));
    }
}
package 归并排序;

/**
 * @author 2902996750
 * @version 1.0
 * @date 2022/10/5 11:17
 * ToComparable类:存放排序所需要的比较方法
 */
public class ToComparable {

    /**
     * 比较方法,返回大的对象
     * @param a 对象a
     * @param b 对象b
     * @return 最大的值
     */
    public static boolean compare(int[] arg,int a, int b){
        return arg[a]-arg[b]>0;
    }

    /**
     * 交换两个元素的位置
     */
    public static void exchange(int[] arg,int a,int b){
        int c;
        c=arg[b];
        arg[b]=arg[a];
        arg[a]=c;
    }

    /**
     * 对整个数组进行排序
     * @param arg 要排序的数组
     */
    public static void sort(int[] arg){
        //1.得到对应的起始点和结束点
        int a=0;
        int b=arg.length-1;
        //2.调用重写的排序方法对其进行排序
        sort(arg,a,b);
    }


    /**
     * 对指定下标的数组就行排序
     * @param arg 要排序的数组
     * @param a 排序数组的起始点
     * @param b 排序数组的结束点
     */
    public static void sort(int[] arg,int a,int b){
        //必须保证a<b,不能出现从下标6到5,或者0到0这种情况
        if (a<b){
            //获取到从哪里分的那个位置
            int min=a+(b-a)/2;
            sort(arg,a,min);
            sort(arg,min+1,b);
            merge(arg,a,min,b);
        }
    }

    /**
     * 把数组进行合并
     * @param arg 要排序的数组
     * @param a 第一个要合并数组的起始点
     * @param b 第一个要合并数组的结束点
     * @param c 第二个要合并数组的结束点
     */
    public static void merge(int[] arg,int a,int b,int c){
        //1.初始化一个与arg等长的数组
        int[] args = new int[arg.length];
        //2.定义三个指针:一个指向创建的数组对象模板lo,另外两个分别指向要合并的数组对象 p1,p2
        int lo=a;
        int p1=a;
        int p2=b+1;
        //3.移动两个要合并对象的指针,比较大小,将小的放到对应模板位置
        while (p1<=b && p2<=c){
            //比较对应索引的值
            if (ToComparable.compare(arg,p1,p2)){
                args[lo]=arg[p2];
                lo++;
                p2++;
            }else {
                args[lo]=arg[p1];
                lo++;
                p1++;
            }
        }
        //4.如果p1的指针最后没有走完,那么顺序移动p1指针,把对应元素放到对应位置
        while (p1<=b){
            args[lo]=arg[p1];
            lo++;
            p1++;
        }
        //5.如果p2的指针最后没有走完,那么顺序移动p2指针,把对应元素放到对应位置
        while (p2<=c){
            args[lo]=arg[p2];
            lo++;
            p2++;
        }
        //6.把模板的数据复制到原数组中
        for (int i = a; i <= c; i++) {
            arg[i]=args[i];
        }
    }
}

六.快速排序------高级排序

package 快速排序;

import java.util.Arrays;

/**
 * @author 2902996750
 * @version 1.0
 * @date 2022/10/5 23:14
 * 实现快速排序:需要不断确定一个分界值,与分界值比较,再对分界值两边数据进行排序
 * 快速排序原理:
 *     1.首先先确定一个分界值a,然后通过该分解值分成左右两个部分
 *     2.将大于等于分界值的数据放到分界值右边,小于分界值的数据放到分界值左边。
 *       此时左边部分中各元素都小于或等于分界值,而右边部分中各元素大于或等于分界值。
 *     3.再对a左边的数据和右边的数据分别进行1,2操作。
 *     4.重复上面操作。
 * 实现过程:
 *     1.首先需要先确定分界值,这里把要排序的数组的第一个数据作为分界值,然后进行排序。
 *     2.然后定义两个指针(也就是对应开始和结尾的索引),让对应指针的值与分界值比较.
 *       从右往左的指针找比分界值小的数据,从左往右找比分界值大的数据。找到后就进行交换。(前提是两个指针没有走到一起,左边指针小于右边指针)
 *     3.当两个指针相等的时候,停止移动,然后将分界值(排序数组的第一个元素)与指针相等所对应位置处的元素进行交换。
 *     4.再对分界值a两边数据进行排序操作。重复此过程。
 */
public class TestKuiShu {
    public static void main(String[] args) {
        int[] arg={5,3,7,5,9,8,2,4,1,6,0};
        ToComparable.sort(arg);
        System.out.println(Arrays.toString(arg));
    }
}
package 快速排序;

/**
 * @author 2902996750
 * @version 1.0
 * @date 2022/10/5 11:17
 * ToComparable类:存放排序所需要的比较方法
 */
public class ToComparable {

    /**
     * 比较方法,返回大的对象
     * @param a 对象a
     * @param b 对象b
     * @return 最大的值
     */
    public static boolean compare(int[] arg,int a, int b){
        return arg[a]-arg[b]>0;
    }

    /**
     * 交换两个元素的位置
     */
    public static void exchange(int[] arg,int a,int b){
        int c;
        c=arg[b];
        arg[b]=arg[a];
        arg[a]=c;
    }

    /**
     * 对整个数组进行排序
     * @param arg 要排序的数组
     */
    public static void sort(int[] arg){
        //起始点索引
        int a=0;
        //结束点索引
        int b=arg.length-1;
        sort(arg,a,b);
    }


    /**
     * 对指定下标的数组就行排序
     * @param arg 要排序的数组
     * @param a 排序数组的起始点
     * @param b 排序数组的结束点
     */
    public static void sort(int[] arg,int a,int b){
        if (a<b){
            //需要对数组中a到b元素进行分组(左子组,右子组),返回分界值变化后的索引
            int partition = partition(arg, a, b);
            //让左子组有序
            sort(arg,a,partition-1);
            //让右子组有序
            sort(arg, partition+1, b);
        }
    }

    /**
     * 对数组从a到b进行分组
     * @param arg 要分的数组
     * @param a 起始点
     * @param b 结束点
     * @return 返回分组的分界值变化后所在的索引
     */
    public static int partition(int[] arg,int a,int b){
        //确定分界值:就是一直比较的那个值
        int key = arg[a];
        //定义两个指针,分别指向带切分的最小值和最大值
        int lo=a;
        int hi=b;
        while (true){
            //先从右往左扫描,找到比分界值小的停止
            while (arg[hi]>key){
                if (hi==lo){
                    break;
                }
                hi--;
            }
            //再从左往右扫描,找到比分界值大的停止
            while (arg[lo]<=key){
                if (lo==hi){
                    break;
                }
                lo++;
            }
            //交换这两个值
            if (lo<hi){
                exchange(arg,lo,hi);
            }else {
                break;
            }
        }
        exchange(arg,a,lo);
        return lo;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值