简单排序大法
作者:互联网
排序算法
说到排序,学过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.冒泡排序
思想:
- 比较相邻的元素。如果前一个元素比后一个元素大,就交换这两个元素的位置。
- 对每一对相邻元素做同样的工作,从开始第一对元素到结尾的最后一对元素。最终最后位置的元素就是最大
值。
实现:通过转载的图来理解下边的代码
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
实现:通过转载的图来理解下边的代码
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.插入排序
思想:
- 把所有的元素分为两组,已经排序的和未排序的;初始时默认下标0处为已排序
- 找到未排序的组中的第一个元素,向已经排序的组中进行插入;
- 倒叙遍历已经排序的元素,依次和待插入的元素进行比较,当待插入元素小于倒序元素时,两者交换。否则退出遍历(因为已排序数组最后一个值小于等于带插入元素时,已为有序不需要交换)
注意:理解思想时的坑,带插入元素满足条件时会交换,莫要掉坑!!!!
实现:通过下图来理解下边的代码
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