作者前言
大家好,我是阿濠,今篇内容跟大家分享的是排序算法之冒泡排序,很高兴分享到segmentfault与大家一起学习交流,初次见面请大家多多关照,一起学习进步.
一、冒泡排序的介绍
基本介绍
冒泡排序(Bubble Sorting) 的基本思想是:通过对待排序序列从前向后(从下标较小的元素开始)
, 依次比较相邻元素的值
,若发现逆序则交换
,使值较大的元素逐渐从前移向后部
,就象水底下的气泡一样逐渐向上冒。
优化思路
(因为排序的过程中
,各元素不断接近自己的位置
,如果一趟比较下来没有进行过交换
,就说明序列有序
,因此可以在排序过程中设置个标志flag判断元素是否进行过交换
。从而减少不必要的比较
。可以在冒泡排序写好后,再进行)
二、应用示例认识冒泡排序
将五个无序的数
: 3,9,-1, 10, 20
使用冒泡排序法
将其排成一个从小到大的有序数列。
步骤思路:
1.需要进行数组大小-1的循环
2.比较相邻的元
素,如果比较大则交换两个
3.对每一对相邻元素作同样的工作
,从开始第一对到结尾的最后一对
代码推演每次排序的过程
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("第一趟排序后的数组");
System.out.println(Arrays.toString(arr));
运行结果如下:
第一趟排序后的数组:[3,-1,9,-2,10]
//第二趟排序,就是将第二大的数排在倒数第二位
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));
运行结果如下:
第二趟排序后的数组:[-1,3,-2,9,10]
//第三趟排序,就是将第三大的数排在倒数第三位
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));
运行结果如下:
第三趟排序后的数组:[-1,-2,3,9,10]
.......
我们发现for循环的相关部分
是相似
,改变的是每次循环的次数
,即进行如下代码抽整:
//进行排序,将最大的数排在最后,时间复杂度是 O(n^2)
for(int i = 0; i < arr.length - 1; i++) {
for(int j=0;j arr[j + 1]) {
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
System. out. println("第"+(i+1)+"趟排序后的数组");
System. out.println(Arrays.toString(arr));
}
运行结果如下:
第1趟排序后的数组:[3,-1,9,-2,10]
第2趟排序后的数组:[-1,3,-2,9,10]
第3趟排序后的数组:[-1,-2,3,9,10]
第4趟排序后的数组:[-2,-1,3,9,10]
使用标志性变量避免交换
加入标志性变量flag
,用于标志某一趟排序过程中是否有数据交换
,如果进行某一趟排序时并没有进行数据交换
,则说明数据已经
按要求排列好
,可立即结束排序
,避免不必要的比较过程
boolean flag=false;
//排序,就是将最大的数排在最后没时间0(n^2)
for(int i = 0; i < arr.length - 1; i++) {
for(int j=0;j arr[j + 1]) {
flag=true;
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
//证明在一趟排序中,没有进行交换
if(!flag){
break;
}else{
//重置flag,进行下次判断
flag=false;
}
System. out. println("第"+(i+1)+"趟排序后的数组");
System. out.println(Arrays.toString(arr));
}
三、复杂度分析
空间复杂度:O(1)
假设数组的元素个数是n
,整个排序的过程中,直接在给定的数组里进行元素的两两交换
。
时间复杂度:O(n^2)
情景一:给定的数组按照顺序已经排好
只需要进行n- 1次的比较
,两两交换次数为0
,时间复杂度是O(n)
,这是最好的情况
。
情景二:给定的数组按照逆序排列
需要进行n(n- 1)/ 2次比较
,时间复杂度是O(n^2)
,这是最坏的情况
。
情景三:给定的数组杂乱无章
在这种情况下,平均时间复杂度是O(n^2)
。