2019-12-16-尾递归

2019-12-23  本文已影响0人  一_贫

https://www.jb51.net/article/126839.htm
返回值是 Stream 的是惰性求值,返回其他或返回空的则是及早求值


import java.util.stream.Stream;
/**
 * 尾递归函数接口
 * @author : martrix
 */
@FunctionalInterface
interface TailRecursion<T> {
    /**
     * 用于递归栈帧之间的连接,惰性求值
     * @return 下一个递归栈帧
     */
    TailRecursion<T> apply();
    /**
     * 判断当前递归是否结束
     * @return 默认为false,因为正常的递归过程中都还未结束
     */
    default boolean isFinished(){
        return false;
    }
    /**
     * 获得递归结果,只有在递归结束才能调用,这里默认给出异常,通过工具类的重写来获得值
     * @return 递归最终结果
     */
    default T getResult()  {
        throw new Error("递归还没有结束,调用获得结果异常!");
    }
    /**
     * 及早求值,执行者一系列的递归,因为栈帧只有一个,所以使用findFirst获得最终的栈帧,接着调用getResult方法获得最终递归值
     * @return 及早求值,获得最终递归结果
     */
    default T invoke() {
        return Stream.iterate(this, TailRecursion::apply)
                .filter(TailRecursion::isFinished)
                .findFirst()
                .get()
                .getResult();
    }
}
/**
 * 使用尾递归的类,目的是对外统一方法
 *
 * @author : Matrix
 */
class TailInvoke {
    /**
     * 统一结构的方法,获得当前递归的下一个递归
     *
     * @param nextFrame 下一个递归
     * @param <T>       T
     * @return 下一个递归
     */
    public static <T> TailRecursion<T> call(final TailRecursion<T> nextFrame) {
        return nextFrame;
    }
    /**
     * 结束当前递归,重写对应的默认方法的值,完成状态改为true,设置最终返回结果,设置非法递归调用
     *
     * @param value 最终递归值
     * @param <T>   T
     * @return 一个isFinished状态true的尾递归, 外部通过调用接口的invoke方法及早求值, 启动递归求值。
     */
    public static <T> TailRecursion<T> done(T value) {
        return new TailRecursion<T>() {
            @Override
            public TailRecursion<T> apply() {
                throw new Error("递归已经结束,非法调用apply方法");
            }
            @Override
            public boolean isFinished() {
                return true;
            }
            @Override
            public T getResult() {
                return value;
            }
        };
    }
}

public class Test {


    public static void main(String[] args) {
        class Solution {
            public TailRecursion<Long> fibTail(int N, Long x, Long y){
                if (N == 0){
                    return TailInvoke.done(x);
                }
                return TailInvoke.call(() -> fibTail(N - 1, y, x + y));
            }
            public Long fib(int N) {
                return fibTail(N, 0L, 1L).invoke();
            }
        }
        Solution solution = new Solution();
        System.out.print(solution.fib(24));
    }
}
上一篇 下一篇

猜你喜欢

热点阅读