美文网首页
2019-12-16-尾递归

2019-12-16-尾递归

作者: 一_贫 | 来源:发表于2019-12-23 11:43 被阅读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));
    }
}

相关文章

  • 2019-12-16-尾递归

    https://www.jb51.net/article/126839.htm返回值是 Stream 的是惰性求值...

  • Kotlin语言(九):特性

    1、尾递归优化 尾递归:函数在调用自己之后没有再执行其他任何操作就是尾递归 尾递归优化的原理就是将递归转换成迭代,...

  • 递归&尾递归

    调用栈的特点,先进后出, FILO, 场景还原。 递归 有栈溢出的可能 stack overflow 尾递归 编译...

  • 递归调用优化

    尾递归优化 函数调用自身,称为递归。如果尾调用自身,就称为尾递归。 递归非常耗费内存,因为需要同时保存成千上百个调...

  • 什么是尾调用?什么是尾递归?尾调用的优化?尾递归优化?

    尾调用优化 尾递归(尾调用优化)

  • C++ 递归算法

    递归算法,尾递归算法求阶乘!

  • 25.尾递归优化

    1.代码如下: 只有尾递归才能优化 1.需要将递归转化为尾递归2.加上关键字tailrec 2.尾递归的原理,看编...

  • 尾调用优化

    尾调用优化 尾递归 正常递归 尾递归 改写以上代码,使其只有一个参数: 总结一下,递归本质上是一种循环操作。纯粹的...

  • 斐波那茨数列的几种解法

    首先关于尾递归递归:你先帮我把下面搞定,撇准好我再来尾递归:我直接先上再说 用尾递归写费波纳茨数列 用快速幂+矩阵...

  • 尾递归

    函数调用自身,称为『递归』;函数尾调用自身,称为『尾递归』 由于递归需要保存大量调用帧,很消耗内存,容易发生 st...

网友评论

      本文标题:2019-12-16-尾递归

      本文链接:https://www.haomeiwen.com/subject/lnkdnctx.html