乍一看这个需求是完不成的,因为冒泡排序算法基本原理决定了需要两层循环结构。
要完成一个“真正的冒泡排序”至少要做到:
- 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
- 对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。第一轮完成后,最后的元素应该会是最大的数。
- 针对除最后一个元素外的所有的元素重复以上的步骤,获得第二大的数。这里是第一层循环。
- 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。这里是第二层循环。
- 特别的,当一轮比较过程中没有发生交换,则说明所有元素顺序已经正确,直接结束比较。
那难道真的没有办法在不使用循环结构的情况下实现满足这五点的排序算法吗?
其实是可以做到的,有一种手段可以实现类似于循环的功能,那就是递归。
想想求n的阶乘的方法,除了写一个循环体从1乘到n,还可以定义递归函数f(1)=1, f(x)=x*f(x-1)。这样就在不用循环的情况下完成了循环的功能。
那么要怎样通过递归实现满足上面5个要求的排序算法呢?首先想想这个函数应该有几个变量。
数组肯定要,当然靠定义全局变量也可以。
当前位置肯定要,因为比较的是相邻元素,所以一个就够。
需要一个变量反应循环轮次,如果一轮没结束,应该继续比较下两个元素;而一轮结束了则要开始新一轮。这个变量可以是当前这轮需要执行比较的最后一个元素的位置。
还需要一个标志位来判断这一轮冒泡过程中是否发生了交换,如果没有那在一轮结束的时候就应该结束排序。
一种可行的实现结果如下所示。需要注意第一次调用的时候结束位置是倒数第二个元素,因而是a.lenth-2。
public class BubbleSort {
private static void bubbleSortWithoutLoop(int[] a, int pos, int endPos, boolean noChange){
// compare & bobble
if(a[pos]>a[pos+1]){
int temp = a[pos];
a[pos] = a[pos+1];
a[pos+1] = temp;
noChange = false;
}
// is the end of this round?
if(pos<endPos){
// continue this round
bubbleSortWithoutLoop(a,pos+1,endPos,noChange);
} else {
// if there has next round and need to go next round
if(endPos>0 && !noChange){
// next round
bubbleSortWithoutLoop(a,0,endPos-1,true);
}
// otherwise end the sort
}
}
public static void main(String[] args){
int[] a = {4,10,8,2,1,11,9,5,6,3,7};
bubbleSortWithoutLoop(a,0,a.length-2,true);
System.out.println(Arrays.toString(a));
}
}
输出结果:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
Process finished with exit code 0