排序算法的种类
为了便于理解,最好debug处理每一步
1. 冒泡排序算法
1、执行流程:
① 从头开始比较每一对相邻元素,如果第1个比第2个大,就交换它们的位置
✓ 执行完一轮后,最末尾那个元素就是最大的元素
② 忽略 ① 中曾经找到的最大元素,重复执行步骤 ①,直到全部元素有序
2.冒泡思想
(1)对要排序的序列从前到后依次比较相邻的元素的值,若发现逆序则交换,使值较大的元素从前往后移。
(2)总共arr.length-1
次大的循环
每一次大循环代表一趟排序,每次排序比较相邻两个两个元素的值,比较后两个元素都后移(这里想象成两个索引都后移)
3.算法实现
public static void bubbleSort(int[] arr){
/**
* 第一轮排序结束后,确定了第一大的数
* 第二轮排序结束后,确定了第二大的数
* 第三轮排序结束后,确定了第三大的数
* ......
* 第n-1轮排序结束后,确定了第n-1大的数
*
* 如果数组的长度为n,在将n-1个数确定好后,最后一个自然是最小的
* 所以共需要n-1轮排序
*/
for(int i=0;i<arr.length-1;i++){
/**
* 在每轮排序中,比较相邻两个数的大小,如果前面的数比后面的数大就交换位置
* 第一轮排序i=0,n个数需要比较n-1次
* 第二轮排序i=1,第一大的数已经确定不需要再进行比较,n-1-1次
* 第三轮排序i=2,第二大的数已经确定不需要再进行比较,n-1-1-1次
*/
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;
}
}
}
}
冒泡排序优化①:
如果序列已经完全有序,可以提前终止冒泡排序。不需要再执行排序操作了,因为已经有序了
package com.atguigu.排序算法;
import java.util.Arrays;
/**简单测试 冒泡排序*/
public class 冒泡排序test {
public static void main(String[] args) {
int [] arr ={3,7,2,19,4};
boolean flag = false; // 标识变量,表示是否进行过交换
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]){
flag = true;
temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
//优化排序,不然是4趟排序
if (!flag) { // 在一趟排序中,一次交换都没有发生过
System.out.println("第"+(i+1)+"趟排序,一次交换都没有发生过");
break;
} else {
flag = false; // 重置flag!!!, 进行下次判断
}
System.out.println(Arrays.toString(arr));
System.out.println("第"+(i+1)+"趟排序的倒数第"+(i+1)+"位数为最大数"+arr[arr.length-1-i]);
}
System.out.println("---------------------------------");
System.out.println("最终冒泡排序结果:"+Arrays.toString(arr));
}
}
完整代码:包含最坏、平均时间复杂度: O(n2) ◼ 最好时间复杂度: O(n)
package com.atguigu.排序算法;
import java.text.SimpleDateFormat;
import java.util.Date;
public class BubbleSort {
public static void main(String[] args) {
// int arr[] = {3, 9, -1, 10, 20};
//
// System.out.println("排序前");
// System.out.println(Arrays.toString(arr));
//为了容量理解,我们把冒泡排序的演变过程,给大家展示
//测试一下冒泡排序的速度O(n^2), 给80000个数据,测试
//创建要给80000个的随机的数组
int[] arr = new int[80000];
for(int i =0; i < 80000;i++) {
arr[i] = (int)(Math.random() * 8000000); //生成一个[0, 8000000) 数
}
Date data1 = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String date1Str = simpleDateFormat.format(data1);
System.out.println("排序前的时间是=" + date1Str);
//测试冒泡排序
bubbleSort(arr);
Date data2 = new Date();
String date2Str = simpleDateFormat.format(data2);
System.out.println("排序后的时间是=" + date2Str);
//System.out.println("排序后");
//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("第二趟排序后的数组");
System.out.println(Arrays.toString(arr));
// 第三趟排序,就是将第三大的数排在倒数第三位
for (int j = 0; j < arr.length - 1 - 2; j++) {
// 如果前面的数比后面的数大,则交换
if (arr[j] > arr[j + 1]) {
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
System.out.println("第三趟排序后的数组");
System.out.println(Arrays.toString(arr));
// 第四趟排序,就是将第4大的数排在倒数第4位
for (int j = 0; j < arr.length - 1 - 3; j++) {
// 如果前面的数比后面的数大,则交换
if (arr[j] > arr[j + 1]) {
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
System.out.println("第四趟排序后的数组");
System.out.println(Arrays.toString(arr)); */
}
// 将前面额冒泡排序算法,封装成一个方法
public static void bubbleSort(int[] arr) {
// 冒泡排序 的时间复杂度 O(n^2), 自己写出
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.println("第" + (i + 1) + "趟排序后的数组");
//System.out.println(Arrays.toString(arr));
if (!flag) { // 在一趟排序中,一次交换都没有发生过
break;
} else {
flag = false; // 重置flag!!!, 进行下次判断
}
}
}
}