Java:递归 - 用递归实现冒泡,和解决递归返回值问题

不能用for/while,使用递归实现冒泡

和for/while一样,只是迭代的参数都要写成传参否则会丢失状态

下面的代码loop表示每次的冒泡遍历次数,执行时依次递减。

递归冒泡代码:

/*
   * 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等包装类不行)。

猜你喜欢

转载自blog.csdn.net/OliverZang/article/details/84942768