1、冒泡排序
排序思路:冒泡排序只会操作相邻的两个数据。每次冒泡操作都会对相邻的两个元素进行比较,看是否满足大小关系要求。如果不满足就让它俩互换。
举例:
实现代码:
public class BubbleSort {
public static void sort(int[] arr) {
int len = arr.length;
if (len <= 1) {
return;
}
for (int i = 0; i < len; i++) {
//提前退出标志
boolean flag = true;
for (int j = 0; j < len - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
flag = false;
}
}
if (flag) {
return;
}
}
}
public static void main(String[] args) {
int[] arr = {3, 1, 2, 4, 5, 6, 8, 7};
sort(arr);
System.out.println(Arrays.toString(arr));
}
}
复杂度:
1、空间复杂度为 O(1),是一个原地排序算法。
2、时间复杂度为 O(n^2)。
3、稳定的排序算法。
2、插入排序
排序思路:将数组中的数据分为两个区间,已排序区间和未排序区间。初始已排序区间只有一个元素,就是数组的第一个元素。插入算法的核心思想是取未排序区间中的元素,在已排序区间中找到合适的插入位置将其插入,并保证已排序区间数据一直有序。重复这个过程,直到未排序区间中元素为空,算法结束。举例:
实现代码:
public class InsertSort {
public static void sort(int[] arr) {
int len = arr.length;
if (len <= 1) {
return;
}
for (int i = 1; i < len; i++) {
int val = arr[i];
int j = i - 1;
for (; j >= 0; j--) {
if (arr[j] > val) {
arr[j + 1] = arr[j];
} else {
break;
}
}
//j + 1 因为 j 为 -1 了
arr[j + 1] = val;
}
}
public static void main(String[] args) {
int[] arr = {3, 1, 2, 4, 6, 5, 7};
sort(arr);
System.out.println(Arrays.toString(arr));
}
}
复杂度:
1、空间复杂度为 O(1),是一个原地排序算法。
2、时间复杂度为 O(n^2)。
3、稳定的排序算法。
3、选择排序
排序思路:选择排序算法的实现思路有点类似插入排序,也分已排序区间和未排序区间。但是选择排序每次会从未排序区间中找到最小的元素,将其放到已排序区间的末尾。举例:
实现代码:
public class SelectSort {
public static void sort(int[] arr) {
int len = arr.length;
if (len <= 1) {
return;
}
for (int i = 0; i < len; i++) {
int val = arr[i];
int index = i;
for (int j = i; j < len; j++) {
if (arr[index] > arr[j]) {
index = j;
}
}
arr[i] = arr[index];
arr[index] = val;
}
}
public static void main(String[] args) {
int[] arr = {4, 5, 6, 3, 2, 1};
sort(arr);
System.out.println(Arrays.toString(arr));
}
}
复杂度:
1、空间复杂度为 O(1),是一个原地排序算法。
2、时间复杂度为 O(n^2)。
3、非稳定的排序算法。