冒泡排序及优化
冒泡排序算法的原理如下:
- 1.比较相邻的元素。如果第一个比第二个大,就交换他们两个.
- 2.对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
- 3.针对所有的元素重复以上的步骤,除了最后一个。
- 4.持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
针对步骤一,二:代码如下,遍历整个数组第一轮比较将最大的数下沉到最底部
//3 1 5 8 2 9 4 6 7-->1 3 5 2 8 4 6 7 9
//比较,筛选出当前列最大的数放到最后
for (int j = 1; j < array.length; j++) {
if (array[j] > data[j + 1]) {
int temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
}
针对步骤三,四代码如下: 从第一位到倒数第二位置:做一次步骤一,二的两两比较排序:
//从后面逐步减少遍历个数
for (int i = array.length-1; end > 0; i--) {
步骤一
}
所以:冒泡排序的总体算法如下
public static void bubbleSort(int[] array){
//3 1 5 8 2 9 4 6 7 n*(n-1)/2 n
//第一轮比较结果:1 3 5 2 8 4 6 7 9 数字最大的沉到最低
for(int i=array.length-1;i>0;i--) {
for (int j = 0; j < i; j++) {
if (array[j] > array[j + 1]) {
int temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
flag=false;
}
}
}
}
总体运行如下:
@Test
public void testSort(){
int[] array=new int[]{3,2,5,8,1,9,4,6,7};
for (int i : array) {
System.out.print(i+" ");
}
System.out.println("\n");
bubbleSort(array);
for (int i : array) {
System.out.print(i+" ");
}
}
public static void bubbleSort(int[] array){
//3 1 5 8 2 9 4 6 7 n*(n-1)/2 n
//第一轮比较结果:1 3 5 2 8 4 6 7 9 数字最大的沉到最低
for(int i=array.length-1;i>0;i--) {
for (int j = 0; j < i; j++) {
if (array[j] > array[j + 1]) {
int temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
flag=false;
}
}
}
}
运行结果如下:
冒泡排序的时间复杂度是:O(n^2)。
优化一
如果swap一次都没执行,说明当前元素已经是有序的了
public static void bubbleSort(int[] array){
//3 1 5 8 2 9 4 6 7 n*(n-1)/2 n
//第一轮比较结果:1 3 5 2 8 4 6 7 9 数字最大的沉到最低
for(int i=array.length-1;i>0;i--) {
boolean flag=true;
for (int j = 0; j < i; j++) {
if (array[j] > array[j + 1]) {
int temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
flag=false;
}
}
if(flag){
break;
}
}
}
优化二
可以记录最后一次交换的位置,最后一次交换位置后续的元素就是有序的。 比如说: 3,4,1,5,7,10其中最后一次是1的位置,他后面的位置就是有序的,没有必要再比较了。 所以下一轮再进来的时候只需要将前面无序的再扫描一遍就行:
private static void sort3(int[] array) {
//从后面逐步减少遍历个数
for (int end = array.length - 1; end > 0; end--) {
//sortIndex最后会复制给end,
//sortIndex需要考虑完全有序的时候,end会就是初始值,
//此时要退出循环,所以可以设置1,0等让下次循环条件不符合。
int sortIndex = 0;
//比较,筛选出当前列最大的数放到最后
for (int start = 1; start <= end; start++) {
if (array[start] <array[start - 1]) {
swap(array,start,start-1);
//记录最后一次交换的位置
sortIndex = start;
}
}
//缩小下一轮扫描范围
end = sortIndex;
}
}
private static void swap(int[] data, int first, int end) {
int temp = data[first];
data[first] = data[end];
data[end] = temp;
}
运行:
@Test
public void testSort() {
// int[] array=new int[]{3,2,5,8,1,9,4,6,7};
int[] array = new int[]{3, 4, 1, 5, 7, 10};
for (int i : array) {
System.out.print(i + " ");
}
System.out.println("\n");
sort3(array);
for (int i : array) {
System.out.print(i + " ");
}
}
结果: