不确定是否要发布到PSE或SO,但我的问题是关于递归。
假设我有一些递归运行的函数MergeSort。如果我想计算它分割数组前半部分的次数,我会在哪里放置计数器? (我知道我可以计算它,但我想更好地理解递归)。
所以,例如
function u = MergeSort(Array)
%% Initializations
A = Array;
B = zeros(1,n2); %to store first half of A
C = zeros(1,n1-n2); %to store second half of A
D = zeros(1,n1); %to store sorted array
na = length(A);
nb = floor(0.5*na);
count1 = 0;
count2 = 0;
%% recursive part
if n1 == 1
D = A;
A1 = mergeSort(A(1:nb));
A2 = mergeSort(A(nb+1:n));
答案 0 :(得分:3)
function (sorted_array, total) = mergesort(array) {
if(length(array) == 1)
then return (array, 0); // this is not a split, don't count it
(left, left_sum) = mergesort(lefthalf);
(right, right_sum) = mergesort(righthalf);
result_array = merge(left, right);
return (result_array, 1 + left_sum + right_sum); // this is a split, add 1
}
这不仅可以计算上半场的分数,而且只能在前半场调用它。您可以通过将0更改为1来更改它以计算所有函数调用。
关于这一点(以及一般的递归)的一个很酷的事情是它实际上只是重述你想要计算的定义。如果我们从分支机构返回,我们分支机构总数的定义是什么?一个对我们来说,无论多少都添加在左侧和右侧。如果我在底部并且我要回来了,那么我们有多少分支在下来?零。
答案 1 :(得分:1)
最简单的方法是将计数器作为参数传递给递归函数本身,类似于以下内容:
func foo(bar, acc) {
print bar;
print acc;
foo(bar+1, acc+1);
}
然后,当您最初调用该函数时,您可以按如下方式执行此操作:
foo(bar, 0);
显然它有点多于此(你可能希望函数做的不仅仅是打印当前变量,你可能还需要确保它有一个结束案例),但希望基本的想法能够实现。我认为,我建议阅读有关模式匹配,折叠和尾递归的信息,这对理解计数器和累积很有帮助。为了解释它是如何有用的,我最近花了很多时间使用Erlang,它非常重视递归和尾调用(在函数中可能没有直接使用的计数器,但有效地执行了同样的事情通过使用所谓的尾部调用到列表为空的点。