一.冒泡排序
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;
}
}