【问题标题】:Reverse a list using recursion使用递归反转列表
【发布时间】:2014-04-13 10:28:01
【问题描述】:

我正在做一本关于 Erlang 的书中的示例。这是任务:在不使用 BIF 的情况下编写反向函数。

这就是我所做的:

reverse([H | T]) -> [reverse(T) | [H]];
reverse([]) -> [].

这是这个函数返回的内容:

(emacs@localhost)3> examples:reverse([1, 2, 3]).
[[[[],3],2],1]

我不明白如何让它返回扁平列表[3, 2, 1]。有可能吗?

【问题讨论】:

    标签: erlang


    【解决方案1】:

    正如你所说,你只需要展平。

    所以要么在你的 examples:reverse/1 函数之后使用 lists:append/1,要么用 reverse([H | T]) -> reverse(T) ++ [H]; 替换 reverse([H | T]) -> [reverse(T) | [H]];

    然后,代码在算法上变得非常低效,这就是为什么 lists:reverse/1,2 是 BIF。

    【讨论】:

      【解决方案2】:

      在语法 [H|T] 中,H 是一个元素,T 是一个列表(至少对于 proplist 而言),在您的代码中 [reverse(T) | [H]] 创建一个列表,其中第一个元素是 reverse(T) 的结果,而tail 是单个元素列表[H]

      如果你想这样实现功能,你应该使用 fenollp 提出的语法。

      如果要编写高效的代码,应避免对部分结果进行多次中间复制,并避免non tail recursive calls(以限制调用堆栈的大小:

      reverse(L) -> reverse(L,[]). % use an accumulator to create a tail recursive function
      
      reverse([],R) -> R;
      reverse([H|T],R) -> reverse(T,[H|R]). % all [H|R] can be fully evaluated before recursively calling reverse
                                            % this is what is called a tail recursive function
                                            % in addition, the construction of [H|T]
                                            % does not require to make a copy of T
      

      【讨论】:

        【解决方案3】:

        你可以使用折叠:

        lists:foldl(fun(X, Acc) -> [X | Acc] end, [], [1,2,3]).
        

        【讨论】:

          【解决方案4】:

          您不必将结果放入列表中。 这对我来说很好:

          reverse([]) -> [];
          reverse([H | T]) -> reverse(T) ++ [H].
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2020-07-22
            • 2018-11-16
            • 2022-08-12
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多