如果比较取决于返回值,尾递归是否可能?

发布于 2024-10-01 10:03:55 字数 565 浏览 5 评论 0原文

我有一个家庭作业,要求使用直接递归来查找数组中最左边、最低的负整数的索引的函数。附加要求是函数的参数为​​数组和大小,并且无效值的返回值为 -999。

我想出了这个:

int LowIndexMinNeg(int src[], int size)
{
    if (size == 0)
       return -999;
    int index = LowIndexMinNeg(src, size - 1);

    if (index >= 0)
       return (src[size - 1] < src[index]) ? (size - 1) : index;
    else
       return (src[size - 1] < 0) ? (size - 1) : index;
} 

它有效,满足要求,并让我获得满分。可以用尾递归来实现吗?

在我看来,既然你必须从递归调用中获取结果来进行比较,以决定是否传递该结果或更新它,这是不可能的,但递归仍然让我的大脑陷入困境,所以我可能缺少一些明显的东西。

注意:我的家庭作业已经上交并评分。

I had a homework assignment that asked for a function that uses direct recursion to find the index of the left-most, lowest, negative integer in an array. Additional requirements were for the parameters of the function to be the array and the size and that the return value for no valid value was -999.

I came up with this:

int LowIndexMinNeg(int src[], int size)
{
    if (size == 0)
       return -999;
    int index = LowIndexMinNeg(src, size - 1);

    if (index >= 0)
       return (src[size - 1] < src[index]) ? (size - 1) : index;
    else
       return (src[size - 1] < 0) ? (size - 1) : index;
} 

It works, satisfies the requirements, and got me full credit. Can this be implemented with tail recursion?

It seems to me that since you have to take the result from the recursive call to use in a comparison to decide if you pass that one on or update it that it wouldn't be possible but recursion still ties my brain in knots a it so there might be something obvious that I'm missing.

Note: My homework assignment was already turned in and graded.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

混吃等死 2024-10-08 10:03:55

如果在返回之前对递归结果进行变换,则它不是尾递归。

编辑:话虽如此,如果您想让函数尾部递归:

const int SENTINEL= 0;

int LowIndexMinNeg(int src[], int size, int index)
{
    if (size == 0)
    {
        if (index<0 || src[index]>=0)
            return -999;
        else
            return index;
    }

    int current_index= size - 1;
    int new_index= src[current_index]<=src[index] ? current_index : index;

    return LowIndexMinNeg(src, size - 1, new_index);
} 

并调用 LowIndexMinNeg(src, src_size, src_size - 1)

编辑2:找到术语最左的最负值。您可以将其表述为第一个最负值的索引。

EDIT3:删除大部分条件,因为更容易找到最低值的索引,然后检查它是否为负数。

If you transform the result of recursion before returning, it is not tail recursive.

EDIT: Having said that, if you want to make the function tail recursive:

const int SENTINEL= 0;

int LowIndexMinNeg(int src[], int size, int index)
{
    if (size == 0)
    {
        if (index<0 || src[index]>=0)
            return -999;
        else
            return index;
    }

    int current_index= size - 1;
    int new_index= src[current_index]<=src[index] ? current_index : index;

    return LowIndexMinNeg(src, size - 1, new_index);
} 

And call as LowIndexMinNeg(src, src_size, src_size - 1)

EDIT2: finding the poorly termed leftmost most negative value. You can probably state that as the index of the first most negative value.

EDIT3: removing most of the conditionals, since it's easier to find the index of the lowest value, then check if it's negative.

梅窗月明清似水 2024-10-08 10:03:55

您需要将迄今为止找到的最小数字存储在某处。通过你的函数,你正在使用堆栈
来存储它。

使用尾递归函数,您需要存储迄今为止在其他地方找到的最小数字。
例如:

  • 作为全局变量(呃..)。
  • 作为函数本身的参数。
  • 作为成员变量

您对函数的要求可能排除了所有这些,因此您留下了类似于您所拥有的代码的内容,该代码无法编写为尾递归。

要了解例如最后一点:

  int LowIndexMinNeg(int src[], int size,int current_lowest = 0,int lowest_index = 0) {
     if(size == 0)
        return current_lowest == 0 ? -999 : lowest_index;
     int val = src[size - 1] ;
     if(val < 0 && val  < current_lowest) {
        current_lowest = val;
        lowest_index = size -1;
     }
      return LowIndexMin(src,size - 1,current_lowest,lowest_index);
   }

并且

struct find_smallest {
  int current_lowest = 0;
  int lowest_index = 0

   int LowIndexMinNeg(int src[], int size) {
     if(size == 0)
        return current_lowest == 0 ? -999 : lowest_index;
     int val = src[size - 1] ;
     if(val < 0 && val  < current_lowest) {
        current_lowest = val;
        lowest_index = size - 1;
     }
      return LowIndexMin(src,size - 1);
   }
};

You need to store the lowest number found so far somewhere. With your function you're using the stack
to store that.

With a tail recursive function you'll need to store the lowest number found so far elsewhere.
e.g:

  • As a global variable (ugh..).
  • As a parameter to the function itself.
  • As a member variable

The requirement you have for your function probably rules out all those, so you're left with something like the code you have, which cannot be written to be tail-recursive.

To get an idea of e.g. the 2 last point:

  int LowIndexMinNeg(int src[], int size,int current_lowest = 0,int lowest_index = 0) {
     if(size == 0)
        return current_lowest == 0 ? -999 : lowest_index;
     int val = src[size - 1] ;
     if(val < 0 && val  < current_lowest) {
        current_lowest = val;
        lowest_index = size -1;
     }
      return LowIndexMin(src,size - 1,current_lowest,lowest_index);
   }

And

struct find_smallest {
  int current_lowest = 0;
  int lowest_index = 0

   int LowIndexMinNeg(int src[], int size) {
     if(size == 0)
        return current_lowest == 0 ? -999 : lowest_index;
     int val = src[size - 1] ;
     if(val < 0 && val  < current_lowest) {
        current_lowest = val;
        lowest_index = size - 1;
     }
      return LowIndexMin(src,size - 1);
   }
};
夏九 2024-10-08 10:03:55

以下是使用尾递归实现该功能的方法:

int LowIndexMinNeg(int src[], int size, int index = 0, int lowest_index = -999, int lowest_value = 0)
{
    if (index >= size) {
        return lowest_index;
    }
    if (src[index] < lowest_value) {
        return LowIndexMinNeg(src, size, index+1, index, src[index]);
    } else {
        return LowIndexMinNeg(src, size, index+1, lowest_index, lowest_value);
    }
}

此实现使用默认参数将函数全部放在一起,但这会导致界面混乱。如果您愿意,可以将其拆分为两个函数:

static int LowIndexMinNegHelper(int src[], int size, int index, int lowest_index, int lowest_value)
{
    if (index >= size) {
        return lowest_index;
    }
    if (src[index] < lowest_value) {
        return LowIndexMinNegHelper(src, size, index+1, index, src[index]);
    } else {
        return LowIndexMinNegHelper(src, size, index+1, lowest_index, lowest_value);
    }
}


int LowIndexMinNeg(int src[], int size)
{
    return LowIndexMinNegHelper(src, size, 0, -999, 0);
}

在本例中,LowIndexMinNegHelper 只需是一个本地函数(我在上面用 static 表示)。

Here's how you might implement that using tail recursion:

int LowIndexMinNeg(int src[], int size, int index = 0, int lowest_index = -999, int lowest_value = 0)
{
    if (index >= size) {
        return lowest_index;
    }
    if (src[index] < lowest_value) {
        return LowIndexMinNeg(src, size, index+1, index, src[index]);
    } else {
        return LowIndexMinNeg(src, size, index+1, lowest_index, lowest_value);
    }
}

This implementation uses default arguments to keep the function all together, but this makes for a messy interface. You can split this into two functions if you like:

static int LowIndexMinNegHelper(int src[], int size, int index, int lowest_index, int lowest_value)
{
    if (index >= size) {
        return lowest_index;
    }
    if (src[index] < lowest_value) {
        return LowIndexMinNegHelper(src, size, index+1, index, src[index]);
    } else {
        return LowIndexMinNegHelper(src, size, index+1, lowest_index, lowest_value);
    }
}


int LowIndexMinNeg(int src[], int size)
{
    return LowIndexMinNegHelper(src, size, 0, -999, 0);
}

In this case, LowIndexMinNegHelper only needs to be a local function (which I've indicated with static above).

贵在坚持 2024-10-08 10:03:55

我可能有一个提案,但当然我必须更改签名:

int LowIndexMinNeg(int src[], int size, int min = -999)
{
  if (size == 0)
    return min;

  const int min_value = (min == -999) ? 0 : src[min];
  return LowIndexMinNeg(src, size - 1, src[size - 1] <= min_value ? size - 1 : min);
}

I might have a proposal, but of course I had to change the signature :

int LowIndexMinNeg(int src[], int size, int min = -999)
{
  if (size == 0)
    return min;

  const int min_value = (min == -999) ? 0 : src[min];
  return LowIndexMinNeg(src, size - 1, src[size - 1] <= min_value ? size - 1 : min);
}
末蓝 2024-10-08 10:03:55

我不确定赋值规则是否允许定义辅助函数,但这是当操作的最自然签名不允许时实现尾递归的一种标准转换。例如:

int LowIndexMinNeg2(int src[], int size, int min)
{
    if (size == 0) return min;
    src--; size--; 
    if (min >= 0) min++;

    if (src[0] < 0
    && (min < 0 || src[0] <= src[min])) 
        min = 0;

    return LowIndexMinNeg2(src, size, min);
} 

int LowIndexMinNeg2(int src[], int size)
{
    return LowIndexMinNeg2(src + size, size, -999);
} 

该版本还颠倒了遍历的顺序,以便能够将“min”的“真实”值与“未找到”值区分开来。其他可能更具可读性的方法将涉及使用额外的累加器来获取实际最小值(而不仅仅是索引)和/或数组中的当前偏移量(以便可以按“正常”顺序进行遍历。但是当然,如果我编写这样的代码用于认真使用,我首先不会使用递归。

I'm not sure whether the rules for the assignment would have permitted defining an auxiliary function, but that is one standard transformation for achieving tail recursion when the most natural signature of the operation does not permit it. For example:

int LowIndexMinNeg2(int src[], int size, int min)
{
    if (size == 0) return min;
    src--; size--; 
    if (min >= 0) min++;

    if (src[0] < 0
    && (min < 0 || src[0] <= src[min])) 
        min = 0;

    return LowIndexMinNeg2(src, size, min);
} 

int LowIndexMinNeg2(int src[], int size)
{
    return LowIndexMinNeg2(src + size, size, -999);
} 

This version also reverses the order of traversal to make it possible to distinguish a "real" value of 'min' from the 'not found' value. Other, likely more readable, approaches would involve making use of additional accumulators for the actual minimum value (instead of only an index) and/or the current offset into the array (so that traversal can be done in "normal" order. But of course if I were coding something like this for serious use I wouldn't be using recursion in the first place.

三月梨花 2024-10-08 10:03:55

你可以用两个静态来做到这一点......

int LowIndexMinNeg(int src[], int size)
{
  static int _min = 0;
  static int _index = 0;

  if (size == 0) return -999;
  if (_index == size) return (src[_min] < 0) ? _min : -999;
  if (src[_index] < 0 && src[_index] < src[_min]) _min = _index;
  ++_index;
  return LowIndexMinNeg(src, size);
}

You could do this with two statics...

int LowIndexMinNeg(int src[], int size)
{
  static int _min = 0;
  static int _index = 0;

  if (size == 0) return -999;
  if (_index == size) return (src[_min] < 0) ? _min : -999;
  if (src[_index] < 0 && src[_index] < src[_min]) _min = _index;
  ++_index;
  return LowIndexMinNeg(src, size);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文