卧榻睹此盛世颜,此生亦算共枕眠
分为上下两篇完全是为了能放两次冰冰的美照 o(* ̄▽ ̄*)ブ
写这篇博客主要用来记录自己快速过8大排序算法的心路历程,其中不能保证代码是最优解,但是代码都尽量加上注释或者画图,望各位看官手下留情
时间复杂度和空间复杂度如下:
冒泡排序
Bubble Sort
解释: 通过对待排序的序列从前到后开始,依次比较相邻两数的大小(这次我要求从小到大排序),若发现逆序(左边大右边小),则交换元素位置 假设待排数组为 634921
每次都将较大的数往后稍,这其中有一个优化算法,如果一轮下来发现没有交换这个过程,证明已经是有序的了
这个冒泡排序也没什么好说的,直接上代码吧
//从小到大排序
public class Bubble {
public static void main(String[] args) {
int[] arr ={2,6,1,7,11,7,66,2,7,9,-1};
sort(arr);
System.out.println(Arrays.toString(arr));
//输出:[-1, 1, 2, 2, 6, 7, 7, 7, 9, 11, 66]
}
public static void sort(int[] arr) {
//这里的length-1 是因为下边用的是arr[j]与arr[j+1]比较,防止下标越界
int len = arr.length-1;
int temp = 0;
//该flag用于记录是否移动过数组
boolean flag = false;
for (int i = 0; i < len; i++) {
for (int j = 0; j < len-i; j++) {
if(arr[j] > arr[j+1]){
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
flag = true;
}
}
if(!flag){
return;
}
//记得下一轮开始之前要将flag重置
flag = false;
}
}
}
选择排序
Selection Sort
解释: 从欲排序的数据中,按指定的规则选出某一元素,再依规定交换位置后达到排序的目的 简单来说就是找最小或者最大值,丢在
待排序的数组最前面,然后接着往下继续排
public class SelectSort {
public static void main(String[] args) {
int[] arr ={2,6,1,7,11,7,66,2,7,9,-1};
sort(arr);
System.out.println(Arrays.toString(arr));
}
public static void sort(int[] arr) {
int len = arr.length - 1;
for (int i = 0; i < len; i++) {
//用来记录最小值
int min = arr[i];
//用来记录最小值所在的下标
int minIndex = i;
for (int j = i+1; j < len+1; j++){
if (min > arr[j]){
min = arr[j];
minIndex = j;
}
}
if(minIndex != i ){
//说明最小值有过变化,将待排序的队头与最小的数进行交换
arr[minIndex] = arr[i];
arr[i] = min;
}
}
}
}
插入排序
Insertion sort
把 n 个待排序的元素看成为一个
有序表和一个无序表,开始时有序表中只包含一个元素,无序表中包含有 n-1 个元素,排序过程中每次从无序表中取出第一个元素,把它的排序码依次与有序表元素的排序码进行比较,将它插入到有序表中的适当位置,使之成为新的有序表
public class InsertionSort {
public static void main(String[] args) {
int[] arr = {2, 6, 1, 7, 11, 7, 66, 2, 7, 9, -1};
sort(arr);
System.out.println(Arrays.toString(arr));
}
//要求从小到大排序
public static void sort(int[] arr) {
int len = arr.length;
for (int i = 1; i < len; i++) {
int insertIndex = i;
int insertVal = arr[i];
while (insertIndex >= 1 && insertVal < arr[insertIndex - 1]) {
//如果当前这个待插入的值比当前的值大,继续往前面找
//下面这个操作会使arr[insertIndex-1]在数组中有两个相同的值,也就是出了while循环后为什么可以直接将insertVal插入指定位置的原因
arr[insertIndex] = arr[insertIndex - 1];
insertIndex--;
}
//出来之后,这个insertIndex就是应该插入的位置了
if (insertIndex != i) {
arr[insertIndex] = insertVal;
}
}
}
}
希尔排序
Shell Sort
解释:希尔排序是把记录按下标的一定
增量分组(gap),对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至 1 时,整个文件恰被分成一组,算法便终止 在插入排序中,如果无序表较后的数是一个特别小的数,那么会导致它插入有序表时,有序表中需要有大量的数组移动操作 基于这种现象,提出了缩小增量排序,也就是希尔排序,通过分组完成插入法,从而解决上述问题
public class ShellSort {
public static void main(String[] args) {
int[] arr = {2, 6, 1, 7, 11, 7, 66, 2, 7, 9, -1};
sort(arr);
System.out.println(Arrays.toString(arr));
}
//仍是从小到大
public static void sort(int[] arr) {
int len = arr.length;
for (int gap = len / 2; gap > 0; gap /= 2) {
//从gap开始是因为,前面gap个数都是每组中第一位数,也就是插入算法中默认的有序数组中的第一个数
//并且每次获取的i都相当于从无序表中获取的数,只需要管好自己与前面排好的有序表中的值的位置关系即可
for (int i = gap; i < len; i++) {
//与之前的插入算法一致
if (arr[i] < arr[i - gap]) {
int shellIndex = i;
int shellVal = arr[i];
while (shellIndex - gap >= 0 && shellVal < arr[shellIndex - gap]) {
arr[shellIndex] = arr[shellIndex - gap];
shellIndex -= gap;
}
arr[shellIndex] = shellVal;
}
}
}
}
}