冒泡排序
冒泡排序是一种比较简单的排序算法,其基本思想是:通过对待排序序列从前向后(从下标较小的元素开始),依次比较相邻元素的值,若发现逆序则交换,使值较大的元素逐渐从前移向后部,可以形象的理解为像水底下的气泡一样逐渐向上冒,较大的数字沉底,较小的数字上浮。
算法描述:
i
从0开始,i
与i+1
比较,如果i>i+1
,那么就互换i
不断增加,直到i<n-1
(n是数组元素的个数,n-1
是数组已经最后一个元素) ,一趟
下来,可以让数组元素中最大值排在数组的最后面
代码调试
从最简单开始,首先我们创建一个数组,该数组有3位数字:
int [] arrays={3,2,1};
外层循环是排序的趟数
排序趟数只需要比较arrays.length - 1
在第一趟排序结束后,第3位是最大的了。
一趟 i=0 i<arrays.length-1 i++
比较 {3, 2, 1}
比较第一次 (2 3) 1
比较第二次 2 (1 3)
内层循环是当前趟数需要比较的次数
在第二趟排序结束后,第2位是最大的了。
二趟 i=1 i<arrays.length-1 i++
比较 {2, 1, 3}
比较第一次 (1 2) 3
比较结束
Java代码实现冒泡排序(优化前)
public class BUB {
public static void main(String[] args) {
int[] arrays = {3, 2, 1};
System.out.println("排序前: " + Arrays.toString(arrays));
//冒泡排序
bubbleSort(arrays);
System.out.println("排序后: " + Arrays.toString(arrays));
}
private static void bubbleSort(int[] arrays) {
// 每一趟排序,就是将最大的排序在最后
//外层循环是排序的趟数
// arrays.length-1防止数组下标越界
for (int i = 0; i < arrays.length-1; i++) {
//内层循环是当前趟数需要比较的次数
// arrays.length-1-i 是为了减少比较的次数
for (int j = 0; j < (arrays.length-1)- i; j++) {
if (arrays[j] > arrays[j+1]) {
int temp = arrays[j];
arrays[j] = arrays[j+1];
arrays[j+1] = temp;
}
}
}
}
使用大量数据测试冒泡排序的时间
public class BUB {
public static void main(String[] args) {
int[] arrays = new int[80000];
for (int i = 0; i < 80000; i++) {
// 会生成[0,1000000)的数
arrays[i] = (int)(Math.random() * 1000000);
}
Date date1 = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String datestr1 = simpleDateFormat.format(date1);
System.out.println("排序前的时间是:"+datestr1);
// 调用冒泡排序方法
bubbleSort(arrays);
Date date2 = new Date();
String datestr2 = simpleDateFormat.format(date2);
System.out.println("排序前的时间是:"+datestr2);}
排序前的时间是:2020-03-12 20:40:28
排序前的时间是:2020-03-12 20:40:39
最优算法
// 交换旗帜变量 = 假 (False)
// 从 i = 1 到 最后一个没有排序过元素的指数
// 如果 左边元素 > 右边元素
// 交换(左边元素,右边元素)
// 交换旗帜变量 = 真(True)
// while 交换旗帜变量
Java代码实现冒泡排序(优化后)
public static void bubbleSort(int[] arr) {
// 每一趟排序,就是将最大的排序在最后
int temp = 0; //临时变量
boolean flag = false; // 标识变量,表示是否进行过交换
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]) {
flag = true;
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
if (!flag) { // 在一趟排序中,一次交换都没有发生过
break;
} else {
flag = false; // 重置flag,进行下次判断
}
}
}
使用大量数据测试冒泡排序的时间
全部代码
public class BUB {
public static void main(String[] args) {
int[] arrays = {3,2,1};
System.out.println("排序前: " + Arrays.toString(arrays));
//冒泡排序
bubbleSort(arrays);
System.out.println("排序后: " + Arrays.toString(arrays));
}
public static void bubbleSort(int[] arr) {
// 每一趟排序,就是将最大的排序在最后
int temp = 0; //临时变量
boolean flag = false; // 标识变量,表示是否进行过交换
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]) {
flag = true;
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
if (!flag) { // 在一趟排序中,一次交换都没有发生过
break;
} else {
flag = false; // 重置flag,进行下次判断
}
}
}
}
时间复杂度
优化前:
- 最优的时间复杂度:O(n^2) --------------------------> 此种情况下在排序的开始已经排好序
- 最坏的时间复杂度:O(n^2) --------------------------> 此种情况下在排序的开始为逆序
- 平均的时间复杂度:O(n^2)
存留
public class BUB {
public static void main(String[] args) {
/* Scanner sc = new Scanner(System.in);
int[] arr = new int[3];//[sc.nextInt()];
for (int i = 0; i < arr.length; i++) {
arr[i] = sc.nextInt();
}
sc.close();*/
int[] arr = {3,2,1};
System.out.println("排序前:"+Arrays.toString(arr));
bubbleSort(arr);
System.out.println("排序后:"+Arrays.toString(arr));
}
public static void bubbleSort(int[] arr) {
boolean flag = false;
// 外循环,一共循环数组长度-1次
for (int i = 0; i < arr.length; i++) {
// 内循环,每次只需要排序沉底元素之前的元素
for (int j = 0; j < arr.length - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
flag = true;
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
if (!flag) { // 在一趟排序中,一次交换都没有发生过
break;
} else {
flag = false; // 重置flag,进行下次判断
}
}
}
}
//通过字符串转化成数组 String[] s = sc.nextLine().split(" ");
// int num[]=new int[s.length];
// num[i]=Integer.parseInt(String.valueOf(s[i]));