参考:https://www.cnblogs.com/guoyaohua/p/8600214.html?tdsourcetag=s_pcqq_aiomsg
文章目录
1.冒泡排序(Bubble Sort)
1.1基本思想
两两比较大小,大的沉下去(放后面),小的浮起来(放前面)。
1.2算法描述
- 比较相邻的两个数,如果第一个大就交换位置
- 对每一对相邻的元素做比较,这样最大的数就在最后的位置
- 重复以上步骤,除了最后已经排好序的数
- 重复步骤1~3,直到排序完成
1.3动图演示
1.4算法分析
- 平均时间复杂度 O(n^2) ,最佳情况O(n), 最差情况O(n^2)
空间复杂度 O(1)
1.5JAVA代码实现
public static int[] bubbleSort(int[] array){
if(array.length == 0){
return array;
}
for(int i=0;i<array.length-1;i++){ //比较a.length-1轮即可,比较一轮找到一个
for(int j=0;j<array.length-1-i;j++){ //无序区间[0,a.length-1-i)
if(array[j+1]<array[j]){
int temp = array[j+1];
array[j+1] = array[j];
array[j] = temp;
}
}
}
return array;
}
如果你对循环的边界设定不清楚,可以看下这张图:
1.6算法优化实现
- 每次比较都使用一个temp变量,同一个空间。
- 如果外层循环循环一次内层都没有发生交换,即比较一轮都没有交换的说明数组有序。
- 内层循环时,如果最后有几次并没有交换,说明只需要比较到上次交换的位置即可。
public static int[] bubbleSort(int[] array){
if(array.length == 0){
return array;
}
int temp;
int changeIndex = 0; //最后一次交换的位置
int sortIndex = array.length; //无序区间的边界
for(int i=0;i<array.length-1;i++){
boolean flag = true; //优化2
for(int j=0;j<sortIndex;j++){
if(array[j+1]<array[j]){
temp = array[j+1];
array[j+1] = array[j];
array[j] = temp;
changeIndex = j; //记录最后一次发生交换的位置
flag = false; //发生了交换
}
}
sortIndex = changeIndex; //改变无序区间的边界
if(flag){ //这一轮一次交换都没有发生,数组有序
return array;
}
}
return array;
}
1.7总结
- 使用场景:适用元素较少的情况下和数组基本有序的情况
- 优点:简单,空间复杂度低,稳定
- 缺点:时间复杂度高,效率慢
*2.选择排序(Selection Sort) *
2.1基本思想
表现最稳定的排序算法之一,在未排序序列中找到最小的元素存放在序列的起始位置,再从剩余未排序序列中继续寻找最小的元素,然后放到已排序序列的末尾,重复执行。
2.2算法描述
- n个元素,初始时:无序区间R[1…n],有序区间为空;
- 到第i趟开始时,有序区间R[1…i-1],无序区间R[i…n]。然后从无序区间找到最小的数和无序区间第一个数交换,这时有序区间变为R[1…i],无序区间变为R[i+1…n];
- n-1趟结束后,数组有序。
2.3动图演示
2.4算法分析
- 平均时间复杂度 O(n^2) ,最佳情况O(n^2), 最差情况O(n^2)
空间复杂度 O(1)
2.5JAVA代码实现
public static int[] selectionSort(int[] array){
if(array.length == 0){
return array;
}
for(int i = 0;i < array.length;i++){
int minIndex = i;
for(int j = i, j < array.length;j++){
if(array[j] < array[mindex]){
minIndex = j;
}
}
int temp = array[minIndex];
array[minIndex] = array[i];
array[i] = temp;
}
return array;
}
2.6算法优化实现
选择排序是一次确定一个元素的位置,而选择排序的优化则是一次确定两个元素的位置,比如降序:每次将最小值放在起始位置,最大值放在末尾位置。这样外层循环的时间缩短了一半,性能也提高了很多。
public static int[] sort(int[] a) {
if(a.length == 0) {
return a;
}
int left = 0;
int right = a.length - 1;
while(left < right) {
int minIndex = left;
int maxIndex = left;
for(int j=left;j <= right;j++) {
minIndex = a[j] < a[minIndex] ? j : minIndex;
maxIndex = a[j] > a[maxIndex] ? j : maxIndex;
}
if(minIndex != left) {
int temp = a[minIndex];
a[minIndex] = a[left];
a[left] = temp;
}
//如果最大元素下标是left,但是前面已经和最小元素交换了,则此时最大元素下标应该是min
if (maxIndex == left){
maxIndex = minIndex;
}
//如果max就是最小的则不用交换
if (maxIndex != right){
int tmp = a[right];
a[right] = a[maxIndex];
a[maxIndex] = tmp;
}
left++;
right--;
}
return a;
}
2.7总结
- 使用场景:适用元素较少的情况下和数组基本有序的情况
- 优点:交换次数少,移动次数确定n次
- 缺点:效率慢,不稳定
*3.插入排序(Insertion Sort) *
3.1基本思想
通过构建有序序列,对未排序的数据从有序序列中从后向前扫描,找到相应位置插入。在这个过程中,需要一直将已排序元素向后移动来为新元素提供空间。
3.2算法描述
- 将第一个数和第二个数排序