- 冒泡排序(Java)
- 1.概念
- 2.思路图解
- 小结:
- 3.演变过程
冒泡排序(Bubble Sort)也是一种简单直观的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢"浮"到数列的顶端。作为最简单的排序算法之一,冒泡排序给我的感觉就像 Abandon 在单词书里出现的感觉一样,每次都在第一页第一位,所以最熟悉。冒泡排序还有一种优化算法,就是立一个 flag,当在一趟序列遍历中元素没有发生交换,则证明该序列已经有序。但这种改进对于提升性能来说并没有什么太大作用。
优化:因为排序过程中,各元素不断接近自己的位置,如果一趟比较下来没有进行过交换,说明序列有序,因此在排序过程中设置一个标志flag判断元素是否进行过交换,从而减少不必要的比较。
2.思路图解原始数组:3,9,-1,10,20
假设有两个指针,第一个指向第一个元素,第二个指向第二个元素,然后比较两个指针所指元素,最后同时进行++操作
第一趟排序:
(1)3,9,-1,10,20 //如果相邻的元素逆序就交换
(2)3,-1,9,10,20
(3)3,-1,9,10,20
(4)3,-1,9,10,20
第二趟排序:
(1)-1,3,9,10,20 //这里可以优化
(2)-1,3,9,10,20
(3)-1,3,9,10,20
第三趟排序:
(1)-1,3,9,10,20
(2)-1,3,9,10,20
第四趟排序:
小结:(1)-1,3,9,10,20
(1)一共进行数组大小-1次大的循环
(2)每一趟排序的次数在减少
(3)如果我们发现在某一趟排序中,没有发生一次交换,可以提前结束冒泡排序
实例:原始数组:3,44,38,5,47,15,36,26,27,2,46,4,19,50,48
3.演变过程package DataStructures.Sort;
import java.util.Arrays;
public class BubbleSort {
public static void main(String[] args) {
int[] arr = {3, 9, -1, 10, -2};
//第一趟排序,将最大的数排在最后
int temp = 0;//临时变量
for (int j = 0; j < arr.length - 1; j++) {
//如果前面的数比后面的大,则交换
if (arr[j] > arr[j + 1]) {
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
System.out.println("第一趟排序后的数组:" + Arrays.toString(arr));
//第二趟排序,将第二大的数排在倒数第二位
for (int j = 0; j < arr.length - 1 - 1; j++) {
//如果前面的数比后面的大,则交换
if (arr[j] > arr[j + 1]) {
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
System.out.println("第二趟排序后的数组:" + Arrays.toString(arr));
//第三趟排序,将第三大的数排在倒数第三位
for (int j = 0; j < arr.length - 1 - 1 - 1; j++) {
//如果前面的数比后面的大,则交换
if (arr[j] > arr[j + 1]) {
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
System.out.println("第三趟排序后的数组:" + Arrays.toString(arr));
//第四趟排序,将第四大的数排在倒数第四位
for (int j = 0; j < arr.length - 1 - 1 - 1 - 1; j++) {
//如果前面的数比后面的大,则交换
if (arr[j] > arr[j + 1]) {
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
System.out.println("第四趟排序后的数组:" + Arrays.toString(arr));
}
}
优化:for循环可以包起来
package DataStructures.Sort;
import java.util.Arrays;
public class BubbleSort {
public static void main(String[] args) {
int[] arr = {3, 9, -1, 10, -2};
//第一趟排序,将最大的数排在最后
int temp = 0;//临时变量
for (int i = 0; i < arr.length - 1; i++) {
for (int j = 0; j < arr.length - 1 - i; j++) {
//如果前面的数比后面的大,则交换
if (arr[j] > arr[j + 1]) {
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
System.out.printf("第%d趟排序后的数组:", i + 1);
System.out.println(Arrays.toString(arr));
}
}
}
时间复杂度:O(n^2)
优化:设置一个flag判断是否进行过交换,减少交换次数
package DataStructures.Sort;
import java.util.Arrays;
public class BubbleSort {
public static void main(String[] args) {
int[] arr = {3, 9, -1, 10, -2};
bubbleSort(arr);
}
public static void bubbleSort(int[] arr) {
int temp = 0;//临时变量
boolean flag = false;//标识变量,表示是否进行过交换
for (int i = 0; i < arr.length - 1; i++) {
for (int j = 0; j < arr.length - 1 - i; j++) {
//如果前面的数比后面的大,则交换
if (arr[j] > arr[j + 1]) {
flag = true;
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
//System.out.printf("第%d趟排序后的数组:", i + 1);
//System.out.println(Arrays.toString(arr));
//在整个一次循环后进行判断
if (!flag) {//在一趟排序中,一次交换都没有发生
break;
}
flag = false;//重置flag,进行下次判断
}
}
}
80000数据测试
public static void main(String[] args) {
// int[] arr = {3, 9, -1, 10, -2};
// bubbleSort(arr);
//80000数组测试
int[] arr = new int[80000];
for (int i = 0; i < 80000; i++) {
arr[i] = (int) (Math.random() * 8000000);//生成[0,8000000)的随机数
}
Date date1 = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String date1Str = simpleDateFormat.format(date1);
System.out.println("排序前时间是" + date1Str);
bubbleSort(arr);
Date date2 = new Date();
String date2Str = simpleDateFormat.format(date2);
System.out.println("排序后时间是" + date2Str);
}



