冒泡排序
目录
基本思想
冒泡排序(Bubble Sort)是一种最简单的交换排序方法,它通过两两比较相邻记录的关键字,如果发生逆序,则进行交换,从而使关键字小的记录如气泡一般逐渐往上“漂浮”(左移),或者使关键字大的记录如石块一样逐渐向下“坠落”(右移)。
代码实现
代码如下:
package sort;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class BubbleSort {
public static void main(String[] args) {
// TODO Auto-generated method stub
List<Integer> array =new ArrayList<Integer>();
Scanner input = new Scanner(System.in);
System.out.println("请输入一组数字:以-1结尾");
while(input.hasNext()) {
int tmp = input.nextInt();
if(tmp!=-1) {
array.add(tmp);
}
if(tmp==-1) {
long startTime = System.nanoTime();
/*冒泡排序
* 思想:每次将相邻的数做比较,大的数向下沉,每进行一轮冒泡后,需要比较的数就会减1(因为每轮都会下沉一个当前最大的数 )
*/
for(int i=1;i<array.size();i++) { //n个数排序最多需要进行n-1次冒泡
for(int j=0;j<array.size()-i;j++) { //注意这里的终止条件是j<array.size()-i;因为n个数需要比较n-1次,第i轮过后剩n-i个数
if(array.get(j)>array.get(j+1)) { //大的数往下沉
int swap=array.get(j+1);
array.set(j+1,array.get(j));
array.set(j, swap);
}
}
}
long endTime=System.nanoTime();
System.out.println("程序运行的时间是:"+(endTime-startTime)+"纳秒");
for(int i=0;i<array.size();i++) {
System.out.print(array.get(i)+" ");
}
array.clear();
}
}
}
}
执行结果如下:
时间复杂度:
需要进行n-1次排序,在每次排序过程中进行n-i次比较,所以,时间复杂度为O(n^2)。
空间复杂度:
冒泡排序只有在两个记录交换位置时,需要一个临时变量用做暂存记录,所以,空间复杂度为O(1)。
仔细阅读上述代码,会发现如果在某趟排序时,并没有记录发生交换,说明,所有记录都有序,则可以排序终止,但上述代码并没有实现这一思想,为了实现这种思想,我们只需要设置一个标记,用来检测每趟排序过程中是否会发生交换即可。
修改后的代码如下:
for(int i=1;i<array.size();i++) { //n个数排序最多需要进行n-1次冒泡
boolean flag=false;
for(int j=0;j<array.size()-i;j++) { //注意这里的终止条件是j<array.size()-i;因为n个数需要比较n-1次,第i轮过后剩n-i个数
if(array.get(j)>array.get(j+1)) { //大的数往下沉
int swap=array.get(j+1);
array.set(j+1,array.get(j));
array.set(j, swap);
flag=true;
}
}
if(!flag) //如果某趟冒泡中没有进行交换,跳出循环
break;
}
再次运行程序:
我们发现,运行时间变短了,当然,这种优化只存在某趟冒泡没有发生记录的交换才起作用,如果初始记录序列逆序,则必须进行n-1趟排序,因此时间复杂度仍为O(n^2)。
还可不可以继续进行优化,答案是肯定的,之前实现的代码,都是每趟冒泡将最大的右移(即单向冒泡),我们可以在每趟排序时,进行双向冒泡,即把最大的放在最右边后,再把最小的放在最左边,这样n个记录最多需要n/2趟排序,修改代码如下:
for(int i=1;i<array.size()/2;i++) { //n个数排序最多需要进行n-1次冒泡
boolean flag=false;
for(int j=0;j<array.size()-i;j++) { //注意这里的终止条件是j<array.size()-i;因为n个数需要比较n-1次,第i轮过后剩n-i个数
if(array.get(j)>array.get(j+1)) { //大的数往下沉
int swap=array.get(j+1);
array.set(j+1,array.get(j));
array.set(j, swap);
flag=true;
}
}
for(int j=array.size()-i-1;j>0;j--) {
if(array.get(j)<array.get(j-1)) { //小的数往上浮
int swap=array.get(j-1);
array.set(j-1,array.get(j));
array.set(j, swap);
flag=true;
}
}
if(!flag) //如果某趟冒泡中没有进行交换,跳出循环
break;
}
再次运行程序:
至于这里显示程序的时间,为什么会增加,我也不知道,楼主弱鸡一枚,我每次运行相同的数据,它都显示不一样。尴尬!!!
这种实现也不会改变冒泡排序的时间复杂度,时间复杂度仍为O(n^2)。