依次交换相邻的两个数,将大的数放后面。
弊端:交换了很多次元素,消耗内存。
时间复杂度度和空间复杂度
简单粗暴的冒泡排序
public static void maopao1(int[] a) {
int tem;
//外层遍历n-1次
for (int i = 0; i < a.length-1; i++) {
//j+1<length-i
for (int j = 0; j < a.length-1-i; j++) {
if (a[j]>a[j+1]) {
tem = a[j+1];
a[j+1] = a[j];
a[j] = tem;
}
}
}
}
第一次优化:当数组为全部有序的状态时,外层循环没有结束的话还是会进行外层循环。可是此时数组已经全部有序了。已经没必要循环下去了
public static void maopao2(int[] a) {
int tem;
boolean isSorted;
//外层遍历n-1次
for (int i = 0; i < a.length-1; i++) {
//在进入内层循环时将布尔值设置为true,加入内层循环一直没有交换元素,
则此时数组已经全部有序了
isSorted = true;
//j+1<length-i
for (int j = 0; j < a.length-1-i; j++) {
if (a[j]>a[j+1]) {
tem = a[j+1];
a[j+1] = a[j];
a[j] = tem;
//内存循环交换元素则令布尔值设置为false
isSorted = false;
}
}
}
}
第二次优化:每进行一次外循环,则数组最后面会多一个有序的值,假设此时必定有序的个数是m(m此时等于外循环执行的次数,每进行一次外循环,m就会加1),但是数组后面中实际有序的个数(假设为n)可能会大于m,n>=m。
找到这个数组后面有序和无序的边界。进行内层循环时,最后一次交换即可理解为该下标就是有序和无序的边界,后面的必定有序(因为没有进行交换了),以后再进行内层循环的时候就没必要再循环该下标后面的数了
public static void maopao3(int[] a) {
int tem;
boolean isSorted;
//有序无序的边界,应该有初始值
int orderedIndex = a.length - 1;
//记录内层循环每次交换时候的下标
int changeIndex = 0;
for (int i = 0; i < a.length-1; i++) {
//在进入内层循环时将布尔值设置为true,加入内层循环一直没有交换元素,
则此时数组已经全部有序了
isSorted = true;
//进行内层循环时,只需要循环到数组的有序边界就可以了,
此时 a.length - 1 - i 必定是大于等于 orderedIndex
for (int j = 0; j < orderedIndex; j++) {
if (a[j]>a[j+1]) {
tem = a[j+1];
a[j+1] = a[j];
a[j] = tem;
//内存循环交换元素则令布尔值设置为false
isSorted = false;
//记录下标,该内层循环结束时,该记录的下标后面的数即为有序
changeIndex = j;
}
}
orderedIndex = changeIndex;
}
}
第三次优化:鸡尾酒排序,见后续~