交换排序之冒泡排序(java实现含优化)

冒泡排序

目录

冒泡排序

基本思想

代码实现


基本思想

       冒泡排序(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)。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值