Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/matlab/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 在递归函数中,我应该在哪里放置计数器?_Algorithm_Matlab - Fatal编程技术网

Algorithm 在递归函数中,我应该在哪里放置计数器?

Algorithm 在递归函数中,我应该在哪里放置计数器?,algorithm,matlab,Algorithm,Matlab,不确定是否要发布到PSE,但我的问题是关于递归的 假设我有一个递归运行的函数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 sec

不确定是否要发布到PSE,但我的问题是关于递归的

假设我有一个递归运行的函数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));

最简单的方法是将计数器作为参数传递给递归函数本身,如下所示:

func foo(bar, acc) {
    print bar;
    print acc;
    foo(bar+1, acc+1);
}
然后,当您最初调用该函数时,可以按如下方式执行:

foo(bar, 0);

很明显,它的功能远不止此(您可能希望函数做一些事情,而不仅仅是打印当前变量,并且您可能还需要确保它有一个最终用例),但希望基本思想能够被理解。我建议阅读有关模式匹配、折叠和尾部递归的知识,我认为这对理解计数器和累加非常有帮助。为了有趣地解释它是如何有帮助的,我最近花了很多时间研究它,它大量使用递归和尾部调用(函数中可能没有直接使用的计数器,但通过使用所述尾部调用到列表为空的点,可以有效地执行相同的操作。

最简单的方法是将计数器作为参数传递给递归函数本身,如下所示:

func foo(bar, acc) {
    print bar;
    print acc;
    foo(bar+1, acc+1);
}
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
}
然后,当您最初调用该函数时,可以按如下方式执行:

foo(bar, 0);
很明显,它的功能远不止此(您可能希望函数做一些事情,而不仅仅是打印当前变量,并且您可能还需要确保它有一个结束用例),但希望基本思想能被理解。我建议阅读有关模式匹配、折叠和尾部递归的知识,我认为这对理解计数器和累加非常有帮助。为了轶事般地解释它是如何有帮助的,我最近花了很多时间在这方面,它大量使用递归和尾部调用(函数中可能没有直接使用的计数器,但通过使用所述尾部调用到列表为空的点,可以有效地执行相同的操作

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,您可以将其更改为计算所有函数调用

关于这一点(以及一般的递归)最酷的事情这实际上只是重新定义了你想要计算的东西。如果我们从一个分支返回,那么从我们开始向下的分支总数的定义是什么?一个对我们来说,加上左边和右边的分支数。如果我在底部返回,从我们开始向下的分支数是多少?零。

这不仅会计算前半部分的拆分,而且您只能在前半部分调用它。通过将0更改为1,您可以将其更改为计算所有函数调用


关于这一点(以及一般的递归)最酷的事情这实际上只是重新定义了你想要计算的东西。如果我们从一个分支返回,那么从我们开始向下的分支总数的定义是什么?一个对我们来说,加上左边和右边的分支数。如果我在底部返回,从我们开始向下的分支数是多少?零。

“问题不能是自身的复制品”…该死的“问题不能是自身的复制品”…damnAlso,如果调用代码不需要了解计数器,那么保持干净很简单:
func foo_public(bar){foo(bar,0);}
此外,如果调用代码不需要知道计数器的信息,那么保持干净也很简单:
func foo_public(bar){foo(bar,0);}