不能用for/while,使用递归实现冒泡
和for/while一样,只是迭代的参数都要写成传参否则会丢失状态
下面的代码loop表示每次的冒泡遍历次数,执行时依次递减。
1. 递归冒泡代码:
/*
* a recursive way of bubbleSort
*@param arr
*the input array of int
*@param i
*the current index of arr
*@param loop
*maximum loops needed for each traverse,started at arr.length-1
*,ended at 1
*@param swap
*an indicator which shall be false when starting the sort
*, showing if a swap happens
*/
public static void bubbleSort(int[] arr, int i, int loop, boolean swap){
if(loop>=1){
if(i<loop){
if (arr[i]>arr[i+1]){
int tmp =arr[i+1];
arr[i+1]= arr[i];
arr[i] = tmp;
swap = true;
}
//inner loop
bubbleSort(arr,++i,loop,swap);
}else{
if (!swap){
return;
}
//reset i and swap,redo outer loop with one less time
bubbleSort(arr,0,--loop,false);
System.out.println(loop);
}
}
}
测试:
int[] arr = {41,21,5,78,13,12,41,1,4,3,4,7,9,9,10,84,72,17,85,100,1,66,23};
bubbleSort(arr,0,arr.length-1,false);
System.out.println("/n"+Arrays.toString(arr));
输出:
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
[1, 1, 3, 4, 4, 5, 7, 9, 9, 10, 12, 13, 17, 21, 23, 41, 41, 66, 72, 78, 84, 85, 100]
思考:输出看起来loop是递增的,但是按照写的代码顺序执行,参数loop不应该是递减的么?
bubbleSort(arr,0,--loop,false);
System.out.println(loop);
可以这样思考,虚拟机栈执行bubbleSort(arr,0,–loop,false)时,后面的执行语句都在栈底中断未执行,此时递归函数又压入了一系列执行语句…操作栈按先进后出的方式执行,当然最后输出的是最先压入未被执行的语句。
总结:在递归函数方法体内,出现在递归函数后面的语句会倒序输出结果。
引申问题:递归函数若有返回值,会返回第一次递归函数的。
由于递归函数最后一次递归的返回值会被之前的不断覆盖,我们得到的往往不是想要的返回值。
比如我们想要用递归累加一个数a,loop次:
public static int accumulation(int a, int loop){
if(loop>0){
a = a*2;
accumulation(a,--loop);
}else{
return a;
}
return a;
}
上面的函数是错误的,让a=1,不管参数loop怎么变,返回值总是2
怎么办呢?
其实就是找个对象存这个数,可以是基本类型,也可以是引用类,但作用域一定是大于函数传参的。
解决方案:递归函数若有返回值,该返回值为成员(全局)变量
public class Accumulation{
private static int result = 0;
public static int accumulation(int a, int loop){
if(loop>0){
a = a*2;
accumulation(a,--loop);
}else{
result = a;
return result;
}
return result;
}
}
a=1,loop=10,上面的函数返回就是1024了。
当然,如果只是测试函数输入输出,也可以main函数内另设静态引用变量比如一个Collection实现类,函数增加这个传参去存这个递归输出(Object和Integer等包装类不行)。
2. 递归选择排序代码:
有了递归冒泡的经验,选择就写得顺畅多了:
选择排序递归需要传递的参数:待排数组,遍历起始下标,遍历次数,最小值下标
public static void selectSort(int arr[],int i,int loop,int min){
if(loop>0){
if(i<arr.length-1){
if(arr[min]>arr[i+1]){
min = i+1;
}
selectSort(arr,++i,loop,min);
}else{
i = arr.length-loop-1;
int tmp = arr[i];
arr[i] = arr[min];
arr[min] = tmp;
selectSort(arr,++i,--loop,i);
}
}
}