冒泡排序、希尔排序和排序算法大总结01:冒泡排序法
基本思想:每次只比较相邻的两个元素,如果前者比后者大就互换,每一轮会找出最大的元素,放在最后的位置,而最后的位置每轮会往前挪一位
循环不变量:第i轮时,arr[n- i, n)已排好序,在arr[n - i - 1]放上正确的元素
实现冒泡排序法
import java.util.Arrays;
public class Algorithm {
public static void main(String[] args) {
Integer[] arr = {4,7,7,5,8,4,2,1};
BubbleSort.sort(arr);
System.out.println(Arrays.toString(arr));
}
}
class BubbleSort {
private BubbleSort(){}
public static<E extends Comparable<E>> void sort(E[] arr){
/**
* 每一轮数组最大边界减1
*/
for (int n = arr.length - 1; n > 0; n--) {
for (int i = 0; i < n; i++) {
if (arr[i].compareTo(arr[i + 1]) > 0) {
swap(arr, i, i + 1);
}
}
}
}
private static<E> void swap(E[] arr, int i, int j){
E temp;
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
冒泡排序法的优化
- 在第二层循环前设置一个标志位,一旦检测到下一轮没有进行元素调换,说明所有的元素都已经排好序了,就直接结束整个循环
- 每一轮循环以后,最后一个元素肯定是最大的已经排好序的,但是倒数的几个元素有可能也已经排好序了,这也是冒泡排序法的特点
因此每次循环时,记录最后一次进行元素调换的位置,不仅可以让下一次循环的终点再往前一点,减少一些重复的比较,还能起到标志位的作用
import java.util.Arrays;
public class Algorithm {
public static void main(String[] args) {
Integer[] arr = {4,7,7,5,8,4,2,1};
BubbleSort.sort(arr);
System.out.println(Arrays.toString(arr));
}
}
class BubbleSort {
private BubbleSort(){}
public static<E extends Comparable<E>> void sort(E[] arr){
/**
* 每次循环最后一位都会放置最大值,因此下次循环可以排除,也即每一轮循环的最大边界减1
* 每次循环前记录下最后一次变化的位置,下一轮循环的最大边界就是这个位置,n进行手动赋值,for循环内可不写
*/
for (int n = arr.length - 1; n > 0;) {
int lastIndex = 0;
for (int i = 0; i < n; i++) {
if (arr[i].compareTo(arr[i + 1]) > 0) {
swap(arr, i, i + 1);
lastIndex = i;
}
}
/**
* 同时可以作为标志位,如果没变说明已经排好序了,可以直接结束
*/
if (lastIndex == 0){
break;
}
n = lastIndex;
}
}
private static<E> void swap(E[] arr, int i, int j){
E temp;
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
复杂度分析
冒泡排序法的时间复杂度为O(n^2)