简化/ Neatify这个双向循环?

时间:2010-09-10 20:49:32

标签: loops iterator simplify two-way

我的电线在某处交叉(或者我的睡眠不足)。我需要一个双向循环,而我当前的代码很简单。

问题:我使用索引运行线性数据结构。我有一个起始指数,比方说120.我想在两个方向交替运行。

实施例: 120,121,119,122,118,123,117,...

我有一个停止标准,需要分别满足每个方向。如果满足一个方向,我只想进入另一个方向,如果两者都满足,我需要退出循环。另外,如果下一个索引无效(数据结构的结尾,比如小于0或大于200),我需要停止。

示例:停止执行116后退和130前进: 120,121,119,122,118,123,117,124,116,(中断),125,126,127,128,129,130​​。

首先跑向一个方向,但遗憾的是另一个方向不是一个选择。

我目前的代码很简单。很多行都没有包含任何“高效”代码。只有迭代逻辑:

  int start_idx = 120;
  int forward_idx = start_idx;
  int backward_idx = start_idx;

  bool next_step_forward = true; //should next step be forward or backward?

  int cur_idx;
  while(backward_idx >= 0 || forward_idx >= 0)
  {
    if(next_step_forward   //if we should step forward
      && forward_idx >= 0) //and we still can step forward
    {
      cur_idx = ++forward_idx;

      if(forward_idx >= 200) //200 is fictive "max index"
      {
        next_step_forward = false;
        forward_idx = -1; //end of data reached, no more stepping forward
        continue;
      }

      if(backward_idx >= 0)
      {
        next_step_forward = false;
      }
    }
    else if(!next_step_forward 
            && backward_idx >= 0)
    {
      cur_idx = --backward_idx;
      if(backward_idx < 0) //beginning of data reached, no more stepping backward
      {
        next_step_forward = true;
        continue;
      }

      if(forward_idx >= 0)
      {
        next_step_forward = true;
      }
    }
    else
    {
      next_step_forward = !next_step_forward; //ever hit?, just security case
      continue; 
    }

    //loop body
    //do something with cur_idx here

    if(stoppingCriterionMet())
    {

      if(cur_idx > start_idx)
      { //this was a forward step, stop forward stepping
        forward_idx = -1;
      }
      else
      { //this was backward step, stop backward stepping
        backward_idx = -1;
      }
    }
  }

我错过了什么吗?任何提示赞赏。感谢。

编辑1:有很多非常好的答案,将“用cur_idx做一些事情”放到一个单独的函数中。虽然这对于我的问题提出的方式是一个完美的想法,但我更喜欢将迭代代码放在其他地方并将生产代码留在那里。我有一个很长的算法,并希望在完成后将其拆分,以最大限度地减少重新安排工作。

4 个答案:

答案 0 :(得分:2)

这个怎么样?

void do_loop(SomeType *arr, int start, int low, int high, int arr_max)
{
    int downwardIndex, upwardIndex;
    downwardIndex = upwardIndex = start;
    while (downwardIndex > 0 && upwardIndex < arr_max) {
        if (downwardIndex < low && upwardIndex > high) {
            break;
        }
        if (downwardIndex > low) {
            processElement(arr[downwardIndex]);
            downwardIndex--;
        }
        if (upwardIndex < high) {
            processElement(arr[upwardIndex]);
            upwardIndex++;
        }
    }
}

答案 1 :(得分:1)

碰巧我今天几乎把这个问题编码了。我使用了C#迭代器函数来完成它。但我认为你想要一个更通用的解决方案。

如果您使用的语言可以构建自己的迭代器(C ++,Java,C#),那么很容易。你只需要创建一个自定义迭代器,它最初从中心开始吐出数字。然后你给迭代器一个额外的函数来告诉它停止在当前方向上运行。

如果你在C中做这样的事情(它看起来对我而言),你可以用包含迭代器状态的结构和你调用的函数来模仿它,以便将它向前推进或停止它。

答案 2 :(得分:1)

首先通过黑客攻击(假设其他语言需要C语言修改,但概念基本上是语言中立的):

void pass1(int start_x, int lo_limit, int hi_limit)
{
    assert(start_x >= lo_limit && start_x <= hi_limit);
    int lo_x = start_x - 1;
    int hi_x = start_x + 1;

    Process(start_x);
    if (StopCriterion(start_x))
        return;  // Is that correct?

    while (lo_x >= lo_limit && hi_x <= hi_limit)
    {
        Process(lo_x);
        if (StopCriterion(lo_x))
            lo_x = lo_limit - 1;
        else
            lo_x--;
        Process(hi_x);
        if (StopCriterion(hi_x))
            hi_x = hi_limit + 1;
        else
            hi_x++;
    }
    while (lo_x >= lo_limit)
    {
        Process(lo_x);
        if (StopCriterion(lo_x))
            lo_x = lo_limit - 1;
        else
            lo_x--;
    }
    while (hi_x <= hi_limit)
    {
        Process(hi_x);
        if (StopCriterion(hi_x))
            hi_x = hi_limit + 1;
        else
            hi_x++;
    }
}

如果起始位置与停止标准匹配,则不清楚会发生什么。搜索应该完全停止,还是应该继续向上,向下或两种方式。我选择了“完全停止”,但可以为列出的任何选项提供案例。在'both'的情况下,你甚至都不愿意进行停止标准检查。

我也选择在向上方向前做下部;它显然是平凡的逆转。最后两个循环的顺序无关紧要,因为如果两个方向都在同一次迭代中终止,则不执行尾随循环;如果只有一个方向被终止,则相应的循环根本不会执行 - 只有另一个方向将执行。

由于那里仍然有重复的代码:

void pass2(int start_x, int lo_limit, int hi_limit)
{
    assert(start_x >= lo_limit && start_x <= hi_limit);
    int lo_x = start_x - 1;
    int hi_x = start_x + 1;

    Process(start_x);
    if (StopCriterion(start_x))
        return;  // Is that correct?

    while (lo_x >= lo_limit && hi_x <= hi_limit)
    {
        Process_lo(&lo_x, lo_limit);
        Process_hi(&hi_x, hi_limit);
    }
    while (lo_x >= lo_limit)
        Process_lo(&lo_x, lo_limit);
    while (hi_x <= hi_limit)
        Process_hi(&hi_x, hi_limit);
}

void Process_lo(int *lo_x, int lo_limit)
{
    Process(*lo_x);
    if (StopCriterion(*lo_x))
        *lo_x = lo_limit - 1;
    else
        *lo_x--;
}

void Process_hi(int *hi_x, int hi_limit)
{
    Process(*hi_x);
    if (StopCriterion(*hi_x))
        *hi_x = hi_limit + 1;
    else
        *hi_x++;
}

可见性控件(静态函数)等被遗漏为实现语言的细节。

答案 3 :(得分:0)

这就是我在C#中接近它的方式:

const int UPPER_BOUND = 200;
const int LOWER_BOUND = 0;
const int START = 120;
bool foundlower = false, foundupper = false;
int upper, lower; 
upper = lower = START;

while (!foundlower || !foundupper) {
    if (!foundlower) {
        if (--lower <= LOWER_BOUND) foundlower = true;
        if (stoppingCriterionMet(lower)) foundlower = true;
    }

    if (!foundupper) {
        if (++upper >= UPPER_BOUND) foundupper = true;
        if (stoppingCriterionMet(upper)) foundupper = true;
    }
}
相关问题