冒泡排序是一种简单的排序算法,它也是一种稳定排序算法。其实现原理是重复走访过要排序的元素列,依次比较两个相邻的元素,如果当该对元素顺序不正确时进行交换过来。一直重复这个过程,直到没有任何两个相邻元素可以交换,就表明完成了排序。
注意: 一般情况下,称某个排序算法稳定;指的是当待排序序列中有相同的元素时,
它们的相对位置在排序前后不会发生改变。
假设待排序序列为 (9,4,1,2),如果采用冒泡排序对其进行升序(由小到大)排序,此时不考虑时间复杂度,有多少个元素就进行多少轮排序,则整个排序过程如下所示:
-
第一轮排序,此时对整个序列中的元素依次扫描每对相邻的元素,并对顺序不正确的元素对交换位置,整个过程如图 1 所示。
从图 1 可以看到,经过第一轮冒泡排序,从序列中找出了最大数 9,并将其放到了序列的尾部。 -
第二轮排序,此时依旧整个序列中的元素依次扫描每对相邻的元素,并对顺序不正确的元素对交换位置,整个过程如图 2所示。
从图2中可以看到,经过第二轮冒泡排序,从序列中找出了第二大数4,并将其放到了序列的倒数第二个位置。 -
第三轮排序,此时依旧整个序列中的元素依次扫描每对相邻的元素,并对顺序不正确的元素对交换位置,整个过程如图 3所示。
从图3中可以看到,经过第三轮冒泡排序,从序列中找出了第三大数2,并将其放到了序列的第二个位置。 -
第四轮排序,此时依旧整个序列中的元素依次扫描每对相邻的元素,并对顺序不正确的元素对交换位置,整个过程如图 4所示。
从图4中可以看到,经过第四轮冒泡排序,从序列中找出了第四大数1,并将其放到了序列的头部。
原始的冒泡排序是稳定的,由于该排序算法的每一轮都要遍历一遍所有的元素,轮转的次数和元素数量相当,所以时间复杂度为O(N^2)。 简单来说,数组里面有多少个元素就进行多少轮的排序,每一轮都依次比较相邻元素,最后就得到我们想要的排序序列。
相应的代码如下:
public class Test {
public static void main(String[] args) {
int[] arr={9,4,1,2};
Mysort(arr);
System.out.println("升序:");
for(int x:arr){
System.out.print(x+" ");
}
}
public static void Mysort(int[] arr) {
int temp=0; //定义的临时变量
for(int i=0;i<arr.length;i++){ //外层循环控制排序的轮次,有多少个元素就排序多少轮
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;
}
}
}
}
}
运行结果为:
仔细观察我们就会发现,上面的代码还是可以稍微改进一下,提高代码的执行效率;首先不管有多少个元素,排序的轮次等于元素的个数减一;上面4个元素,进行4轮排序时,数组内容已经是有序的了,因为经过三轮的排序,数组里面已经有三个元素来到了数组的尾部并且是有序的;如果再进行第4轮排序就属于多余的操作。其次,每一轮比较的次数应该为元素的个数减一再减去第几轮;第一轮时:每个元素都要进行比较,所以比较的次数为:arr.length-1-i,因为i从0开始,所以次数为三;第二轮时:i=1,此时的次数为二,因为经过第一轮的排序,已经找出了最大的一个元素并且放到了数组最后,如果再进行比较也属于多余操作。另外在排序某些数组时进行几轮排序数组就已经是我们想要的序列了,针对这种情况我们可以定义一个标记,来终止排序。
经过分析改进的代码如下:
public class Test {
public static void main(String[] args) {
int[] arr={9,4,1,2};
Mysort(arr);
System.out.println("升序:");
for(int x:arr){
System.out.print(x+" ");
}
}
public static void Mysort(int[] arr) {
int temp=0; //定义的临时变量
boolean a=true; //初始化标记
for(int i=0;i<arr.length-1;i++){ //外层循环控制排序的轮次,共排序arr.length-1轮
a=true; //假设该轮时数组已经有序
for(int j=0;j<arr.length-1-i;j++){ //内层循环控制相邻两个元素进行比较
if(arr[j]>arr[j+1]){ //如果不符合升序规则就进行替换
temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
a=false; //说明素组不是完全有序的
}
}
if(a==true){ //若数组真的有序,则跳出整个循环
break;
}
}
}
}
运行结果: