基础冒泡排序
元素两两相比较,将最大的元素向后排。
冒泡排序外层循环控制循环次数,
内层循环控制每次循环的比较次数
public static void bubbleSort(int[] arr) {
for (int i = arr.length - 1; i > 0; i--) {
for (int j = 0; j < i; j++) {
if (arr[j] > arr[j + 1]) {
arr[j] = arr[j] + arr[j + 1];
arr[j + 1] = arr[j] - arr[j + 1];
arr[j] = arr[j] - arr[j + 1];
}
System.out.print("0");
}
}
}
冒泡排序第一次改进
数组{0, 1, 2, 3, 2, 82, 16, 13, 99, 100, 101, 102};
按照上面未改进的排序方式,在后面元素已经排序有序后,接下来的排序,即前面的数字{0,1,2}已经不需要排序,就是说这三趟排序是多余的,什么也没做。
因此我们在交换的地方增加一个标记,若是那一趟排序并没有交换元素,则说明数组元素已经有序,不用再继续下去。
public static void bubbleSortOptimize1(int[] arr) {
int flag;
for (int i = arr.length - 1; i > 0; i--) {
flag = 0;//标记flag
for (int j = 0; j < i; j++) {
if (arr[j] > arr[j + 1]) {
arr[j] = arr[j] + arr[j + 1];
arr[j + 1] = arr[j] - arr[j + 1];
arr[j] = arr[j] - arr[j + 1];
flag = 1;
}
System.out.print("1");
}
if (flag == 0)
return;
}
}
冒泡排序第二次改进
数组{0, 1, 2, 3, 2, 82, 16, 13, 99, 100, 101, 102};
进行了第一次改进之后,其循环次数已经减少。但是我们发现后排元素{99,100,101,102}也是基本有序的,因此,后排元素的循环判断也是不必要的。
记录下最后一次交换的位置,将循环停止条件设置到此位置结束
设置一个索引值,在数组元素进行交换时,将这个交换的位置用索引值记录下来。一直到循环结束,这个索引值就是最后一次进行交换的位置。
将外层循环的停止条件设置为小于此索引值(最后一次进行交换的位置)继续循环。
public static void bubbleSortOptimize2(int[] arr) {
int flag;
int index;
for (int i = arr.length - 1; i > 0; i--) {
flag = 0;
index = i;
for (int j = 0; j < i; j++) {
if (arr[j] > arr[j + 1]) {
arr[j] = arr[j] + arr[j + 1];
arr[j + 1] = arr[j] - arr[j + 1];
arr[j] = arr[j] - arr[j + 1];
flag = 1;
index = j + 1;
}
System.out.print("2");
}
if (flag == 0)
return;
i = index;
}
}
冒泡排序第三次改进
经过前面两次优化,冒泡排序的效率已经大大提高。
第三次改进思想:每次循环比较寻找一个最大值,并且寻找一个最小值。将最大值置于最后,最小值置于最前。
数组{0, 1, 2, 3, 2, 82, 16, 13, 99, 100, 101, 102};
public static void bubbleSortOptimize3(int[] arr) {
int index;
int flag;
int n = 0;
for (int i = arr.length - 1; i > 0; i--) {
flag = 0;
index = i;
for (int j = n; j < i; j++) {
if (arr[j] > arr[j + 1]) {
arr[j] = arr[j] + arr[j + 1];
arr[j + 1] = arr[j] - arr[j + 1];
arr[j] = arr[j] - arr[j + 1];
flag = 1;
index = j + 1;
}
System.out.print(3);
}
if (flag == 0)
return;
i = index;
for (int j = arr.length - 1; j > n; j--) {
if (arr[j] < arr[j - 1]) {
arr[j] = arr[j] + arr[j - 1];
arr[j - 1] = arr[j] - arr[j - 1];
arr[j] = arr[j] - arr[j - 1];
flag = 1;
}
}
n++;
if (flag == 0)
return;
}
}
测试算法效率
public static void main(String[] args) {
int[] arr1 = {0, 1, 2, 3, 2, 82, 16, 13, 99, 100, 101, 102};
bubbleSort(arr1);
System.out.println();
for (int i : arr1) {
System.out.print(i + "\t");
}
System.out.println();
int[] arr2 = {0, 1, 2, 3, 2, 82, 16, 13, 99, 100, 101, 102};
bubbleSortOptimize1(arr2);
System.out.println();
for (int i : arr2) {
System.out.print(i + "\t");
}
System.out.println();
int[] arr3 = {0, 1, 2, 3, 2, 82, 16, 13, 99, 100, 101, 102};
bubbleSortOptimize2(arr3);
System.out.println();
for (int i : arr3) {
System.out.print(i + "\t");
}
System.out.println();
int[] arr4 = {0, 1, 2, 3, 2, 82, 16, 13, 99, 100, 101, 102};
bubbleSortOptimize3(arr4);
System.out.println();
for (int i : arr4) {
System.out.print(i + "\t");
}
System.out.println();
}
可以看到循环次数的比较 第三次改进之后的循环次数明显比前两种的低。
第三次之后还能再改进吗?
第二次改进时,当后面排好序时,不再进行比较,那么当前面排好序时,能否在逆序循环寻找最小值时不再进行比较。
public static void bubbleSortOptimize3(int[] arr) {
int index;
int index1;
int flag;
int flag1;
int n = 0;
for (int i = arr.length - 1; i > 0; i--) {
flag = 0;
flag1 = 0;
index = i;
for (int j = n; j < i; j++) {
if (arr[j] > arr[j + 1]) {
arr[j] = arr[j] + arr[j + 1];
arr[j + 1] = arr[j] - arr[j + 1];
arr[j] = arr[j] - arr[j + 1];
flag = 1;
index = j + 1;
}
System.out.print(3);
}
if (flag == 0)
return;
i = index;
index1 = 0;
for (int j = arr.length - 1; j > n; j--) {
if (arr[j] < arr[j - 1]) {
arr[j] = arr[j] + arr[j - 1];
arr[j - 1] = arr[j] - arr[j - 1];
arr[j] = arr[j] - arr[j - 1];
flag1 = 1;
index1 = j - 1;
}
System.out.print(4);
}
// n++;
n = index1;
if (flag1 == 0)
return;
}
}
结果为:
看起来好像是提升了效率。