目录
一、选择排序
1. 算法思路
首先从第一个元素到最后一个元素中选择一个最小的元素,将最小的元素和第一个元素进行交换;然后从剩下的元素(第二个元素到最后一个元素)选择最小的元素,将第二个元素与最小的元素进行交换,按照这个过程进行直至到达最后一个元素结束。
2. 算法实现
public class SelectSort {
// min存放最小值的下标,不要直接对数组进行操作
public static int[] selectSort(int[] arr) {
int i = 0, j = 0;
int len = arr.length;
for (i = 0; i < len - 1; i++) {
int min = i;
for (j = (i + 1); j < len; j++) {
// arr[i]与arr[j]进行比较,设置最小值下标
if (arr[min] > arr[j]) {
min = j;
}
}
// swap
int temp = arr[i];
arr[i] = arr[min];
arr[min] = temp;
}
return arr;
}
}
3. 算法分析
选择排序总共需进行(n - 1)趟排序(n表示数组的长度),其中每一趟需要进行(n - (i + 1))次比较,排序总共进行(n - 1) * n / 2次比较,时间复杂度T(n) = O(n²)时间复杂度S(n)= O(1)
二、简单插入排序
1. 算法思路
给定一个待排序数组a,确定{a[0]}为已排序序列,{a[1], a[2] ... a[k] }为待排序列,插入排序顾名思义,选择待排序列的第一个元素ele,通过ele与已排序序列按照从尾比较的方式,如果ele < 当前元素(current), 将current元素后移,如果ele >= 当前元素(cuurent), 停止比较并在current元素下标 + 1 处的元素设置ele,这就是一次插入过程,此时已排序序列为{a[0], a[1]},待排序列为{a[2], a[3], ... a[k]}, 按照这个过程直至待排序列没有元素停止。
2. 算法实现
public static int[] insertSort(int[] arr) {
int i, j;
// 假设第一个元素为有序序列,接下来的一个元素与有序序列从末尾开始依次比较,并插入到合适的位置
int len = arr.length;
for (i = 1; i < len; i++) {
int temp = arr[i];
// 插入思路:若插入元素小于当前元素,那么有序序列当前元素后移
// 如果有序序列元素发生移动,所以(j + 1)处一定是之前的元素,也就是说原来的元素移到了( j + 2)处
// 故直接在(j + 1)处插入元素就行。
for (j = i - 1; j >= 0 && temp <= arr[j] ; j--) {
arr[j + 1] = arr[j];
}
arr[j + 1] = temp;
}
return arr;
}
3. 算法分析
简单插入排序关键在于插入元素与已排序序列的比较过程,考虑最坏情况下,插入元素比任何一个已排序序列中的元素都小,故元素的移动次数为i,此算法时间复杂度为T(n) = O(n²)
空间复杂度S(n) = O(1)
三、冒泡排序
1. 算法思路
冒泡排序是交换排序的一种,正如冒泡一样,它通过相邻元素的比较交换,将满足条件的元素不断上浮,反过来不符合条件的元素会下沉。假设排序数组元素个数为n,那么需要进行(n - 1) 趟比较,每次比较始终从数组首元素开始,通过一趟比较(正序),数组最后一个元素一定是最大元素,因而下一趟的比较不需要对最后一个元素进行比较。冒泡排序的比较策略是设置两个指针pre, current, 每次比较这两个指针所指向的元素,较大者下沉,同时pre、current指针后移,返回执行这个过程,直至完成所有的趟数。
算法优化,假设在第k趟完成了正序排序,那么第(k + 1)趟 到(n - 1)趟是没有必要的,因此设置一个哨兵位,如果一趟中没有进行比较交换,那么哨兵位设置为0,若发生交换,哨兵位设置为1,下一趟比较条件除了判断是否趟数已够还需判断哨兵位的状态。
2. 算法实现
// 双指针 k指向pre元素,j指向current元素
public static int[] bubbleSort(int[] arr) {
int len = arr.length;
// 总共(len - 1)趟
for (int i = 0; i < len - 1; i++) {
// 定义哨兵,用于探测是否需要下一趟冒泡
int count = 0;
int pre = 0;
for (int j = 1; j < (len - i); j++, pre++) {
// 比较arr[i] 与 arr[j] 较大者下沉
if (arr[pre] > arr[j]) {
int temp = arr[pre];
arr[pre] = arr[j];
arr[j] = temp;
// 发生交换,count = 1 表示a[i]~a[j]序列仍可能存在无序
count = 1;
}
}
if (count == 0) {
break;
}
}
return arr;
}
3. 算法分析
冒泡排序 每一趟比较的次数为(n - i - 1), 最坏情况下,每一趟都需进行(n - i - 1)次比较,
时间复杂度T(n) = O(n²), 空间复杂度 S(n) = O(1)
上面三种排序是很经典的排序,算法实现并不复杂,后续我会更新其他经典的排序算法。上述内容如果有错误的地方,希望大佬们可以指正。我一直在学习的路上,您的帮助使我收获更大!觉得对您有帮助的话,还请点赞支持!我也会不断更新文章!