Java实践冒泡排序的优化

Java实践冒泡排序的优化

引言

排序算法的优化问题一直以来都是算法领域的核心问题。优化一种已存在的算法往往需要借助灵活的思维,长久的探索甚至是天马行空的想象力。本文对冒泡排序的优化过程进行了简单实践。

朴素冒泡排序

public static void bubbleSort(int[] array) {
  for(int i = 0;i < array.length - 1;i ++)
  for(int j = 0,temp = 0;j < array.length - 1;j++) {
   if(array[j] > array[j + 1]) {
    temp = array[j];
    array[j] = array[j + 1];
    array[j + 1] = temp;
   }
  }
 }

循环体优化:

对于冒泡排序,一个最简单的优化思路就是,当一个数组已经排序完成的时候,跳出冒泡循环。我们要做的只是在循环之中添加一个判断条件,如果一轮循环之中都没有发生位置交换,则可以跳出循环。

	public static void opt001(int[] array) {  
	        boolean isSorted = true;  
	        for(int i = 0;i < array.length - 1;i ++) {  
	            isSorted = true;  
	            for(int j = 0,temp = 0;j < array.length - 1;j++) {  
	                if(array[j] > array[j + 1]) {  
	                    temp = array[j];  
	                    array[j] = array[j + 1];  
	                    array[j + 1] = temp;  
	                    isSorted = false;  
	                }  
	            }  
	            if(isSorted) break;  
	        }  
	    }  

循环范围优化

我们通过观察发现,冒泡排序的过程中,数组中会存在一个逐渐变大的 “有序区域” 。换言之,数组靠右侧的元素会比左侧的元素更早地达到有序的状态。这种情况下如果再对右侧元素进行冒泡比较就显得多余。一个合理的优化做法就是判定出一个 “有序边界” ,每一轮循环在到达边界时停止。

	public static void opt002(int[] array) {  
	        int border = array.length - 1;  
	        int lastIndex = border;  
	        for(int i = 0;i < array.length - 1;i ++) {  
	            for(int j = 0,temp = 0;j < border;j++) {  
	                if(array[j] > array[j + 1]) {  
	                    temp = array[j];  
	                    array[j] = array[j + 1];  
	                    array[j + 1] = temp;  
	                    lastIndex = j;  
	                }  
	            }  
	            border = lastIndex;  
	        }  
	    } 

下面的版本结合了以上两种优化:

	public static void opt003(int[] array) {  
	        int border = array.length - 1;  
	        int lastIndex = 0;  
	        for(int i = 0;i < array.length - 1;i ++) {  
	            lastIndex = 0;  
	            for(int j = 0,temp = 0;j < border;j++) {  
	                if(array[j] > array[j + 1]) {  
	                    temp = array[j];  
	                    array[j] = array[j + 1];  
	                    array[j + 1] = temp;  
	                    lastIndex = j;  
	                }  
	            }  
	            if(lastIndex == 0) break;  
	            border = lastIndex;  
	        }  
	    }  

天马行空的优化:双向冒泡(鸡尾酒排序)

冒泡排序中会存在乌龟项,也就是一个本该出现在最左边的数字出现在最右边,这种数字让冒泡排序的效率大大降低了。所以,双向冒泡排序解决了这个问题,因为它的比较过程是双向的,就像一个钟摆。

	public static void cockTail(int[] array) {  
	        boolean isSorted = true;  
	        for(int i = 0;i < array.length - 1;i ++) {  
	            isSorted = true;  
	            for(int j = 0,temp = 0;j < array.length - 1;j++) {  
	                if(array[j] > array[j + 1]) {  
	                    temp = array[j];  
	                    array[j] = array[j + 1];  
	                    array[j + 1] = temp;  
	                    isSorted = false;  
	                }  
	            }  
	            if(isSorted) break;  
	            for(int j = array.length - 2,temp = 0;j > 0;j--) {  
	                if(array[j] < array[j - 1]) {  
	                    temp = array[j - 1];  
	                    array[j - 1] = array[j];  
	                    array[j] = temp;  
	                    isSorted = false;  
	                }  
	            }  
	            if(isSorted) break;  
	        }  
	    }  

双向排序plus

这个版本对双向排序的循环体进行了优化(参考上文),可以说是朴素的冒泡排序之中的效率王者,也是简单冒泡排序的一个较完善版本,对不同类型的数组的适应力强。

	public static void cockTailPlus (int[] array) {  
	        int border1 = array.length - 1;  
	        int border2 = 0;  
	        int index1 = 0;  
	        int index2 = array.length - 1;  
	        for(int i = 0;i < array.length - 1;i ++) {  
	            index1 = 0;  
	            for(int j = border2,temp = 0;j < border1;j++) {  
	                if(array[j] > array[j + 1]) {  
	                    temp = array[j];  
	                    array[j] = array[j + 1];  
	                    array[j + 1] = temp;  
	                    index1 = j;  
	                }  
	            }  
	            if(index1 == 0) break;  
	            border1 = index1;  
	            index2 = array.length - 1;  
	            for(int j = border1,temp = 0;j > border2;j--) {  
	                if(array[j] < array[j - 1]) {  
	                    temp = array[j - 1];  
	                    array[j - 1] = array[j];  
	                    array[j] = temp;  
	                    index2 = j;  
	                }  
	            }  
	            if(index2 == array.length - 1) break;  
	            border2 = index2;  
	        }  
	    }  

效率比较

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值