冒泡排序:
转载:https://mp.weixin.qq.com/s/p1wADa_SpYjAz0RyGqODiA
时间复杂度:
最优时间复杂度:O(n^2) (即使元素有序还是需要进行比较)
最坏时间复杂度:O(n^2)
稳定性:稳定
第一轮:比较n-1次
第二轮:n-2次
…
总共比较:n-1+n-2+n-3+…+1=n(n-1)/2
public class BubbleSortTest {
public static void main(String[] args) {
int[] arr = new int[]{6, 5, 4, 1, 3, 2};
System.out.println("排序前数组" + Arrays.toString(arr));
bubbleSort1(arr);
}
// 冒泡排序
public static void bubbleSort1(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) { // 外循环控制比较的轮数,轮数是元素的数量-1
for (int j = 0; j < arr.length - 1 - i; j++) { // 内循环控制每轮比较的元素,轮数越大,比较的次数越少
if (arr[j] > arr[j+1]) { // i和i+1索引比较,也就是相邻元素比较,大的往后放
System.out.print("\t元素 " + arr[j] + " 和 " + arr[j+1] + " 比较, ");
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
System.out.println("比较后" + Arrays.toString(arr));
}
}
System.out.println("排序" + (i+1) + "轮后: " + Arrays.toString(arr));
}
}
}
public class BubbleSortTest {
public static void main(String[] args) {
int[] arr = new int[]{6, 5, 4, 1, 3, 2};
System.out.println("排序前数组" + Arrays.toString(arr));
bubbleSort1(arr);
}
// 冒泡排序
public static void bubbleSort1(int[] arr) {
for (int end= arr.length-1; end >0; end--) { // 外循环控制比较的轮数,轮数是元素的数量-1
for (int j = 0; j < end; j++) { // 内循环控制每轮比较的元素,轮数越大,比较的次数越少
if (arr[j] > arr[j+1]) { // i和i+1索引比较,也就是相邻元素比较,大的往后放
System.out.print("\t元素 " + arr[j] + " 和 " + arr[j+1] + " 比较, ");
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
System.out.println("比较后" + Arrays.toString(arr));
}
}
System.out.println("排序" + (i+1) + "轮后: " + Arrays.toString(arr));
}
}
}
优化1:
public class BubbleSortTest2 {
public static void main(String[] args) {
int[] arr = new int[]{1, 3, 2, 4, 5, 6};
System.out.println("排序前数组" + Arrays.toString(arr));
bubbleSort2(arr);
}
// 优化1:如果有一轮发现没有需要排序的,说明已经有序了.可以不用再遍历比较了
public static void bubbleSort2(int[] arr) { // 0.132s
for (int i = 0; i < arr.length - 1; i++) {
boolean sorted = true; // 用于标记数组是否有序,如果这轮一个元素都没有交换说明有序,后面几轮不需要在排序了
for (int j = 0; j < arr.length - 1 - i; j++) {
if (arr[j] > arr[j+1]) {
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
sorted = false; // 有元素需要交换,说明数组还是无序的.
}
}
if (sorted) {
System.out.println("已经有序了, length = " + arr.length + ", 第 " + (i+1) + "轮");
break;
}
}
}
}
优化2:
有问题:lastposition应该到1就行了,理解思想
public class BubbleSortTest2 {
public static void main(String[] args) {
int[] arr = new int[]{3, 2, 1, 4, 5, 6, 7};
System.out.println("排序前数组" + Arrays.toString(arr));
bubbleSort3(arr);
}
// 优化2:问题是在于j<array.length– i– 1。如果后面已经是有序的就不需要比较
// 下一轮只需要比较到上一轮的最后一次交换的小值那个地方即可
public static void bubbleSort3(int[] arr) { // 0.132s
int lastPosition = 0; // 记录这一轮最后一次比较的较小那个值,下一轮就比较到这里
int len = arr.length - 1; // len表示下一轮要比较到哪里?后面会让len = lastPosition
for (int i = 0; i < arr.length - 1; i++) {
boolean sorted = true; // 用于标记数组是否有序,如果这轮一个元素都没有交换说明有序,后面几轮不需要在排序了
for (int j = 0; j < len; j++) {
if (arr[j] > arr[j+1]) {
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
sorted = false; // 有元素需要交换,说明数组还是无序的.
lastPosition = j; // 记录这一轮最后一次比较的较小那个值,下一轮就比较到这里
} else {
System.out.println("第 " + i + " 轮的第 " + j + " 次不需要交换");
}
}
len = lastPosition;
if (sorted) {
System.out.println("已经有序了, length = " + arr.length + ", i = " + i);
break;
}
}
}
}
冒泡排序是一种交换排序,它的基本思想是:两两比较相邻的数据,大的往后放。使用嵌套循环来实现冒泡排序,外循环控制比较的轮数,内循环控制每轮比较的次数。
冒泡排序可以进行两个优化:
如果有一轮发现没有需要排序的,说明已经有序了,可以不用再遍历比较了,减少比较轮数。
每轮都会比较到array.length– i– 1这个位置,如果后面已经是有序的就不需要比较,下一轮只需要比较到上一轮的最后一次交换的小值那个地方即可,减少每轮的比较次数。
最优时间复杂度:O(n) 当数据本身已经有序如:{1, 2, 3, 4, 5, 6},我们做了优化,比较一轮就结束。