冒泡排序
/**
*步骤:
* 1.比较相邻的元素,如果第一个比第二个大,就交换它们两个
* 2.对每一个相邻元素作相同的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该就是最大的数
* 3.针对所有的元素重复以上的步骤,除了最后一个
* 4/重复步骤1~3,直到排序完成
*
* 总结:
* 1.冒泡排序的时间复杂度是多少?
* 最好情况下,要排序的元素已经是有序的了,我们只需要进行一次冒泡排序,就可以结束了,所以最好情况时间
* 复杂度是O(n),而最坏的情况是,要排除的数据刚好是倒序排列的,我们需要进行n次冒泡操作,所以最坏情况
* 时间复杂度为O(n²)。
* 2.冒泡排序的空间复杂度是多少?
* 冒泡的过程只涉及相邻数据的交换操作,只需要常量级的临时空间,所以它的空间复杂度为O(1),是一种in-place
* 排序算法
* 3.冒泡排序是稳定的排序算法吗?
* 在冒泡排序中,只有交换才可以改变两个元素的前后顺序,为了保证冒泡排序算法的稳定性,当有相邻的连个元素
* 大小相等的时候,我们不做交换,相同大小的数据在排序前后不会改变顺序,所以冒泡排序是稳定的排序算法
*/
public class BubbleSort {
public static void main(String[] args) {
int[] arr = new int[]{1,2,4,3,21,2,4,5,65,25,42,54,25};
BubbleSort bubbleSort = new BubbleSort();
bubbleSort.bubbleSort(arr);
System.out.println(Arrays.toString(arr));
}
public void bubbleSort(int[] arr){
int length = arr.length;
if (length<0) {
return;
}
for (int i=0;i<length;i++) {
for (int j=i+1;j<length;j++) {
if (arr[i]>arr[j]) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
}
}
插入排序
/**
* 原理:将数组中的数据分为两个区间,已排序区间和未排序区间。初始已排序
* 区间只有一个元素,就是数组的第一个元素。插入算法的核心思想是取未排序区间
* 中的元素,在已排序区间中会找到合适的插入元素将其插入,并保证已排序区间数据
* 一直有序,重复这个过程,直到未排序区间中元素为空,算法结束。
* 算法描述:
* 1。从第一个元素开始,该元素可以认为已经被排序
* 2.取出下一个元素,在已经排序的元素序列中从后往前扫描
* 3.如果该元素(已排序)大于新元素,比如26543>265,就把26543的位置往后挪
* 4.重复步骤3,直到找到已排序的元素小于或者等于新元素的位置,比如26543的前一个
* 元素为32,但这时候preIndex--,所以这时候preIndex其实所在位置是32所在位置
* 因此赋值的时候是arr[preIndex+1] = current,即把原本26543的位置顶掉
* 5。重复2-5步骤,即进入下一次for循环,向未排序的数组中再取数值
*
* -------------------------------------------------------------------------
*
* 1.插入排序的时间复杂度是多少
* 如果要排序的数据已经是有序的话,我们并不需要搬任何数据。如果我们从尾到头在
* 有序数据组里面查找插入位置,每次只需要比较一个数据就能去欸的那个插入的位置。
* 所以这种情况下,最好时间复杂度为O(n)。注意这里是从尾到头遍历已经有序的数据
*
* 如果数组的倒序的,每次插入都相当于在数组的第一个位置插入新的数据,所以需要
* 移动大量的数据,所以最坏情况时间复杂度为O(n²)
* 2。插入排序的空间复杂度是多少?
* 插入算法并不需要额外的存储空间,所以空间复杂度是O(1)
*
* 3.插入排序是稳定的排序算法吗?
* 在插入排序中,对于值相同的元素,我们可以选择将后面出现的元素,插入到前面出现元素
* 的后面,这样就可以保持原有的前后顺序不变,所以插入排序是稳定的排序算法
*
* 4.插入排序是直接将未排序的往已排序里面砸,进行重复比较
*/
public class InsertionSort {
public static void main(String[] args) {
int[] arr = new int[]{32,5,4,26543,265,27,52,75,3,7,9};
InsertionSort insertionSort = new InsertionSort();
insertionSort.insertionSort(arr);
System.out.println(Arrays.toString(arr));
}
public void insertionSort(int[] arr) {
//获取当前数组长度
int len = arr.length;
//说明数组只有1个元素或者没有元素
if (len<=1) {
return;
}
//从下标为1,即第二个元素开始对第一个元素进行比较,第一个元素已经排序好了
for (int i=1;i<len;i++) {
//取出当前序列中未排序的元素,即当前要和已排序区间比较的元素
//这里用于记录当前元素
int current = arr[i];
//在有序区间从后往前扫描指针(下标)
//当i=1时,i-1=0
int preIndex = i - 1;
//当下标>=0,即一直循环
//arr[preIndex]>current 当前取出的元素大于要比较的元素
while (preIndex>=0&&arr[preIndex]>current) {
/*大的往后排,小的往前排
前一个数和后一个数进行比较,如果前一个大的话,就把前一个数
赋值给后一个数,重复循环至下标越界
*/
arr[preIndex+1] = arr[preIndex];
/*下标--,即前一个继续比较,也用于放置位置,比如26543和265,265的位置其实是i
26543的位置是i-1,我这里用26543,26543会将265的值覆盖
*/
/*
这时候再--就是32的值了,32的值与current进行比较,即与265进行比较,不符合条件退出
每次比较过后,preIndex要--即与前一个进行比较
*/
preIndex--;
}
//这时候preIndex+1,即32往后退一个,则原本26543的位置会被265取代
arr[preIndex+1] = current;
}
}
}
选择排序
/**
* 原理:
* 分已排序区间和未排序区间,选择排序每次会从未排序区间中
* 找到最小的元素,将其放到已排序的末尾
*
* 总结
* 1.排序的时间复杂度是多少?
* 最好情况时间复杂度为O(n²),最坏情况时间复杂度为O(n²)
* 2。选择排序的空间复杂度是多少?
* O(1)
* 3.选择排序是一个稳定的排序算法吗?
* 选择排序不是一个稳定的排序算法,[4,5,4,1,5],在第一个排序的时候会将下标为3的1和下标
* 为0的4进行替换,则原本下标为1的4和下标为2的4顺序变了,不稳定
*/
public class SelectionSort {
public static void main(String[] args) {
}
public void selectionSort(int[] arr) {
int len = arr.length;
if (len <= 1) {
return;
}
for (int i=0;i<len;i++) {
//这里是计算位置,从未排序的进行选择,即i之前的都是排序好的
int minIndex = i;
//从未排序的序列中找到最小值
for (int j=i;j<len;j++) {
if (arr[j]<arr[minIndex]) {
minIndex = j;
}
}
//记录当前元素
int curr = arr[i];
//将未排序的最小的元素赋给当前元素,即实现最小元素的插入
arr[i] = arr[minIndex];
//这里其实是进行了一个元素的互换
arr[minIndex] = curr;
}
}
}