冒泡排序内外层优化

版权声明:引用本文章请申明参考来源!!! https://blog.csdn.net/zb201666/article/details/88671236
   冒泡排序(Bubble Sort)是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果两个元素的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有顺序交换产生,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。

冒泡排序算法的核心思想如下:

①比较相邻的元素。如果第一个比第二个大,就交换他们两个的顺序。
②对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素总会是最大的数。
③针对所有的元素重复以上的步骤,除了最后一个。
④持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

由于冒泡排序是一种常见的排序方式,针对于其性能的优化也是很有必要的,下面我用java语言来介绍一下我自己的优化方式。希望能有同行的朋友一起探讨探讨。

普通冒泡

    /**
    	 * 校验数组是否为空的方法
    	 * @param arr
    	 */
    	public static void check(int[] arr) {
    		if(arr==null||arr.length<1){
    			System.out.println("数组为空");
    			return;
    		}
    	}

    /**
	 * 普通冒泡升序排序
	 * @param arr
	 */
	public static void sort(int[] arr) {
		check(arr);
		//外层循环次数
		int len = arr.length-1;
		//临时变量
		int temp = 0;
		for(int i = 0;i<len;i++){//外层循环
			for(int j = 0;j<len-i;j++){//内层循环
				if(arr[j]>arr[j+1]){//前一个数比后一个数大则交换
					temp = arr[j];
					arr[j] = arr[j+1];
					arr[j+1] = temp;
				}
			}
		}
	}

外层优化

    /**
	 * 冒泡排序外层优化
	 * 
	 * 问题:
	 * 有的冒泡经过第一轮的交换已经是有序的了,如:2 1 3 4。此时就没必要再继续循环,
	 * 外层的循环次数怎么去控制一下?
	 * 
	 * 
	 * 思想:
	 * 用一个标识变量flag来判断一下,当前数组是否已经有序,
	 * 即内层如果发生了交换就继续循环,内层未发生交换表明数组已经有序,
	 * 如果有序就退出循环,即优化外层的循环次数,这样可以明显的提高冒泡排序的性能。
	 * 
	 * @param arr
	 */
	public static void sort1(int[] arr) {
		check(arr);
		//外层循环次数
		int len = arr.length-1;
		//临时变量
		int temp = 0;
		//判断内层是否发生了交换的标志,false表示没有发生交换,true表示发生了交换
		boolean flag = false;
		for(int i = 0;i<len;i++){//外层循环
			for(int j = 0;j<len-i;j++){//内层循环
				if(arr[j]>arr[j+1]){//前一个数比后一个数大则交换
					temp = arr[j];
					arr[j] = arr[j+1];
					arr[j+1] = temp;
					flag = true;//发生了交换
				}
			}
			if(flag == false){//内层循环一次之后判断是否发生了交换,如果没有则直接结束整个循环
				break;
			}
		}
	}

内层优化

    /**
	 * 冒泡排序内层优化
	 * 
	 * 问题:
	 * 内存循环虽然发生了交换,但是假如一次循环之后第3个位置之后的元素已经有了顺序,
	 * 下次循环时还会再次比较第3个位置之后的元素,此时就没必要再继续比较位置3之后的元素
	 * 怎么去控制一下?
	 * 
	 * 
	 * 思想:
	 * 用一个标识变量loc来记录每次内层循环中最后一次交换的位置,即loc位置后面的元素已经有序
	 * 下次循环只需要循环到loc位置即可,依次类推,直到所有元素都有序为止。
	 * 
	 * 
	 * @param arr
	 */
	public static void sort2(int[] arr) {
		check(arr);
		//外层循环次数
		int len = arr.length-1;
		//临时变量
		int temp = 0;
		//记录每次内层循环最后交换元素的位置
		int loc = 0;
		//控制内层循环次数
		int count = 0;
		for(int i = 0;i<len;i++){//外层循环
			count = len-i;//初始内存循环次数
			for(int j = 0;j<count;j++){//内层循环
				if(arr[j]>arr[j+1]){//前一个数比后一个数大则交换
					temp = arr[j];
					arr[j] = arr[j+1];
					arr[j+1] = temp;
					loc = j;//记录每次内层循环最后交换元素的位置
				}
			}
			count = loc;//下次循环次数loc次
		}
	}

内外层结合

    /**
	 * 冒泡排序内外层优化同时用
	 * 
	 * @param arr
	 */
	public static void sort3(int[] arr) {
		check(arr);
		//外层循环次数
		int len = arr.length-1;
		//临时变量
		int temp = 0;
		//记录每次内层循环最后交换元素的位置
		int loc = 0;
		//控制内层循环次数
		int count = 0;
		//判断内层是否发生了交换的标志,false表示没有发生交换,true表示发生了交换
		boolean flag = false;
		for(int i = 0;i<len;i++){//外层循环
			count = len-i;//初始内存循环次数
			for(int j = 0;j<count;j++){//内层循环
				if(arr[j]>arr[j+1]){//前一个数比后一个数大则交换
					temp = arr[j];
					arr[j] = arr[j+1];
					arr[j+1] = temp;
					loc = j;//记录每次内层循环最后交换元素的位置
					flag = true;//内层发生了交换
				}
			}
			if(flag == false){//没有发生交换则表明已经有序,退出循环
				break;
			}
			count = loc;//下次循环次数loc次
		}
	}

几种优化性能测试

这里我采用随机数随机生成相同元素个数的数组来进行性能测试:

    /**
    	 * 随机生成一个整型数组
    	 * @param begin 随机数开始位置
    	 * @param end   随机数结束为止(不包含)
    	 * @param len   整型数组长度
    	 * @return
    	 */
    	public static int[] createArr(int begin,int end,int len) {
    		int[] arr = new int[len];
    		for (int i = 0; i < arr.length; i++) {
    			//生成一个随机数
    			ThreadLocalRandom localRandom = ThreadLocalRandom.current();
    			int nextInt = localRandom.nextInt(begin, end);
    			arr[i] = nextInt;
    		}
    		return arr;
    	}

	    public static void main(String[] args) {
	    		int[] arr = createArr(0, 1000000, 100000);
	    		System.out.println("=================普通冒泡排序========================");
	    		long start = System.currentTimeMillis();
	    		sort(arr);
	    		long end = System.currentTimeMillis();
	    		System.out.println("普通冒泡排序用时:"+(end-start));
	    		
	    		System.out.println("=================外层优化冒泡排序========================");
	    		long start1 = System.currentTimeMillis();
	    		sort1(arr);
	    		long end1 = System.currentTimeMillis();
	    		System.out.println("外层优化冒泡排序用时:"+(end1-start1));
	    		
	    		System.out.println("=================内层优化冒泡排序========================");
	    		long start2 = System.currentTimeMillis();
	    		sort2(arr);
	    		long end2 = System.currentTimeMillis();
	    		System.out.println("内层优化冒泡排序用时:"+(end2-start2));
	    		
	    		System.out.println("=================内外层优化冒泡排序========================");
	    		long start3 = System.currentTimeMillis();
	    		sort3(arr);
	    		long end3 = System.currentTimeMillis();
	    		System.out.println("内外层优化冒泡排序用时:"+(end3-start3));
	    	}

Eclipse中排序用时测试结果:
Eclispe里插入图片描述
可以看出,排序的数列包含的元素一旦过多,外层优化的效果相对于内层是有明显的优势的,如果实际开发中需要用到冒泡排序,可以采用外层优化的方式来提高排序效率。

猜你喜欢

转载自blog.csdn.net/zb201666/article/details/88671236