当前位置: 首页 > 知识库问答 >
问题:

自定义list_t中的尾递归函数

裴俊能
2023-03-14

我正在从事一个基于C中自定义数据结构list\t的项目。这是可以帮助我操作这个list\t的预定义函数,我被要求编写的函数叫做insert\u list(list\u t,list\u t,int),它是尾部递归的。

typedef Recursive_list list_t;

// EFFECTS: returns true if list is empty, false otherwise
bool list_isEmpty(const list_t& list);

// EFFECTS: returns an empty list.
list_t list_make();

// EFFECTS: given the list (list) make a new list consisting of
//          the new element followed by the elements of the
//          original list. 
list_t list_make(int elt, const list_t& list);

// REQUIRES: list is not empty
// EFFECTS: returns the first element of list
int list_first(const list_t& list);

// REQUIRES: list is not empty
// EFFECTS: returns the list containing all but the first element of list
list_t list_rest(const list_t& list);

// MODIFIES: cout
// EFFECTS: prints list to cout.
void list_print(const list_t& list);

我要编写的insert_list()函数接受两个输入,类型为list_t和一个保证不大于第一个list_t大小的额外整数n,并返回另一个list_t,其中包含第一个list_t中的前n个元素(按它们在原始list_t中出现的顺序),然后是整个第二个html" target="_blank">list\t,然后是第一个list\t的其余元素(整数)。约束条件是该函数及其辅助函数(如果有)必须是尾部递归的。请参见此处的insert_list()原型:

/*
 * REQUIRES: n >= 0 and n <= the number of elements in first
 * EFFECTS: returns a list comprising the first n elements of
 *          "first", followed by all elements of "second",
 *           followed by any remaining elements of "first".
 *
 *     For example: insert (( 1 2 3 ), ( 4 5 6 ), 2)
 *            is  ( 1 2 4 5 6 3 ).
 */
list_t insert_list(list_t first, list_t second, int n);

我花了几天时间思考和尝试解决这个问题的方法,但我得到的最远结果是前n个数字颠倒了。我确实编写了一个函数来反转一个list\t,但我无法反转列表的一部分,只能反转整个列表,而且它不适合我提出的尾部递归结构。我还想知道是否需要编写两个递归函数,这两个函数实际上相互依赖,但在这条路上也没有找到任何有用的解决方案。

共有1个答案

颜思淼
2023-03-14

您需要不断从第一个列表中添加元素,并递减n,直到其达到零。然后,您需要不断添加第二个列表中的元素,直到第二个列表中的元素用尽为止,最后追加第一个列表的其余部分。

编辑:上述描述没有实现尾部递归。因此,我修改了实现。方法是:当n大于零时,保持从第一个元素的前面取下元素,并将其预挂到第二个元素,同时减小n。当n达到零时,执行相反的操作:从第二个元素的前面取下元素,并将其预挂到第一个元素,直到第二个元素为空。这实现了全尾递归实现。

list_t insert_list(list_t first, list_t second, int n)
{
    if(n==0) {
        if(list_isEmpty(second))
            return first;
        else 
            return insert_list(list_make(list_first(second), first), list_rest(second), 0);
    }
    else {
        return insert_list(list_rest(first), list_make(list_first(first), second), n-1);
    }
}
 类似资料:
  • 我有一个家庭作业问题,它给出了一个递归函数,我必须使用尾部递归来实现它。函数为f(0)=1 f(n)=1 2*f(n-1) 我并不擅长尾部递归,我试着查找示例,但我发现的都是没有斐波那契序列的示例,这没有多大帮助。 我真正拥有的是 我知道尾递归基本上每次调用都计算函数,我只是不知道如何实现它。 编辑:我打了一个错字f(n)应该是1 2*f(n-1)

  • 假设我编写这样的代码: 我如何让Kotlin优化这些相互递归的函数,以便在不抛出StackOverflower错误的情况下运行main?tailrec关键字适用于单函数递归,但没有更复杂的功能。我还看到一个警告,在使用关键字tailrec的地方没有找到尾部调用。也许这对编译器来说太难了?

  • 各种各样的书籍、文章、博客帖子表明,将递归函数重写为尾部递归函数可以加快速度。毫无疑问,对于生成斐波那契数或计算阶乘等琐碎情况,它会更快。在这种情况下,有一种典型的重写方法,即使用“辅助函数”和用于中间结果的附加参数。 尾部递归很好地描述了尾部递归函数和非尾部递归函数之间的差异,以及如何将递归函数转换为尾部递归函数。对于这种重写来说什么是重要的-函数调用的数量是相同的(重写之前/之后),不同之处在

  • 问题内容: 我正在尝试在Go中的另一个函数中定义一个递归函数,但是我在努力获取正确的语法。我正在寻找这样的东西: 我想将Function2保留在Function1的范围内,因为它正在访问其范围的某些元素。 如何在Go中执行此操作? 非常感谢 问题答案: 如果它在声明它的行中,则无法访问它的内部。原因是您不是在指 函数, 而是指 变量 (类型是函数),并且只有在声明后才能访问它。 引用规格:声明和范

  • 我对函数式编程很陌生,尤其是下面使用的Scheme。我正在尝试使以下函数是递归的,尾递归的。基本上,该函数的作用是对两个字符串的对齐方式进行评分。当给定两个字符串作为输入时,它会比较每个“列”字符,并根据在称为 scorer 的函数中实现的评分方案(由下面的代码中的函数调用)来累积该对齐的分数。 我有一个想法,用一个帮助函数来累积分数,但我不太确定如何去做,因此我该如何让下面的函数尾递归呢?

  • 尾递归优化 recur 尾递归优化是函数式编程不能缺少的一个性能优化方案. 没有尾递归, 常有的递归调用也会形成很深的调用栈消耗内存. cljs 和 Clojure 类似, 都需要通过声明 recur 进行优化. 最终代码会被编译为 white 结构的 js 代码,从而提高性能. (defn factorial [acc n] (if (<= n 1) acc (recur (* ac