冒牌排序:
从数组开始元素向后两两比较,将大值向后移动。第一遍就会把最大值移动到数组最后,如此往复达到排序目的。
复杂度分析:
比较次数n*(n-1)/2 次
时间复杂度:O(n^2)
普通冒泡排序:
public static int[] BubbleSort1(int arr[],int len){
for (int i = 0; i < len - 1; i++){
for (int j = 0; j < len - 1 - i; j++){
if (arr[j]>arr[j + 1]) {
//交换
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}
return arr;
}
优化一:前有序优化
因为每一次都会比较向后的所有元素,但是如果数组是{6,1,2,3,4,5}那么只需要一次交换数组就已经有序了,后面的几次比较都是无意义的,所以只要在交换的次数的上标记一下,下一次循环如果查不到这个标记就代表数组已经有序了,直接返回就可以了。
public static int[] BubbleSort2(int arr[],int len){
for (int i = 0; i < len - 1; i++){
int flag = 0;
for (int j = 0; j < len - 1 - i; j++) {
if (arr[j]>arr[j + 1]){
//交换
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
flag = 1;//加入标记
}
}
if (flag == 0){
return arr;
}
}
return arr;
}
优化二:后有序优化
对于后半部分有序的数组,我们可以记录一下从哪一位开始数组是有序的,这样下次遍历就不用遍历记录以后的了。
public static int[] BubbleSort3(int arr[],int len){
int k = len - 1;
for (int i = 0; i < len - 1; i++){
int end = 0;//用来记录最后一次交换的位置
int flag = 0;
for (int j = 0; j < k; j++){
if (arr[j]>arr[j + 1]){
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
flag = 1;//加入标记
end = j;//交换元素,记录最后一次交换的位置
}
}
if (flag == 0){
return arr;
}
k = end;//下一次比较到记录位置即可
}
return arr;
}
优化三:正反扫描
正向扫描得到最大值放到最后面,反向扫描得到最小值放到最前面,达到一次扫描确定两个值的目的。
public static int[] BubbleSort4(int arr[],int len){
int n = 0;//同时找最大值的最小需要两个下标遍历
int k = len - 1;
for (int i = 0; i < len - 1; i++)//确定排序趟数
{
int end = 0;
int flag = 0;
//正向寻找最大值
for (int j = n; j < k; j++){
if (arr[j]>arr[j + 1]){
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
flag = 1;//加入标记
end = j;//交换元素,记录最后一次交换的位置
}
}
if (flag == 0){
return arr;
}
k = end;//下一次比较到记录位置即可
//反向寻找最小值
for (int j = k; j > n; j--){
int tmp = arr[j];
arr[j] = arr[j - 1];
arr[j - 1] = tmp;
flag = 1;
}
n++;
if (flag == 0){
return arr;
}
}
return arr;
}