简化/确定这个双向循环?
我把电线穿过某处(或者我没有足够的睡眠)。我需要一个双向循环,而我目前的代码只是简单的丑陋。简化/确定这个双向循环?
问题:我沿着一个使用索引的线性数据结构运行。我有一个开始索引,可以说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做某事”放到一个单独的函数中。虽然这对于我的问题被问到的方式来说是一个完美的想法,但我更喜欢将迭代代码放在其他地方,并将生产代码留在那里。我有一个很长的算法,并希望在完成后将其拆分,以尽量减少重新排列工作。
恰巧我今天编写了这个问题。我使用C#迭代器函数来完成它。但我认为你想要一个更通用的解决方案。
如果您使用可以构建自己的迭代器(C++,Java,C#)的语言,那很容易。您只需制作一个自定义迭代器,最初从中心开始扫出数字。然后你给迭代器一个额外的函数来告诉它停止以当前方向运行。如果你在C中做这样的事情(它看起来像C),你可以用一个包含迭代器状态的结构和你调用的函数来模仿它,使它向前移动或停止它。
低水平几何处理编程的日子似乎抢走了我的面向对象技能。 Gamma等人的设计模式正在从书架上嘲笑我,说“迭代器模式你是白痴,应该自己提出来”。谢谢你的提示。 – B3ret 2010-09-10 21:17:42
第一遍在黑客(假设ç - 需要对其他语言的适应,但其概念基本上是中性语言):
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++;
}
}
目前尚不清楚如果起始位置停止准则相匹配应该发生什么。搜索应该完全停止,还是应该继续向上,向下或两种方式。我选择了“完全停止”,但可以为列出的任何选项制定案例。在“两者”的情况下,您甚至不会执行停止标准检查。
我也选择在上方向前做下方;它显然被微妙地颠倒过来。最后两个循环的顺序并不重要,因为如果两个方向在相同的迭代中终止,则不执行尾循环;如果只有一个方向终止,则相应的循环根本不会执行 - 只有另一个会执行。
,因为在那里仍有反复代码:
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++;
}
可见性控制(静态函数)等离开了作为实现语言的细节。
这个怎么样?
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++;
}
}
}
这是我想接近它在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;
}
}
你应该简化你的问题。而不是“线性数据结构”只是说数组。而不是“停止标准”,只是停留。如果你清理你的问题,你可能会看到一个更清洁的解决方案。 – 2010-09-10 20:57:08
如果这是作业,你应该添加标签 – 2010-09-10 20:57:40
对不起,我会去睡觉来解决这个问题。这不是功课。哪位疯子想纠正学生提出的解决方案? – B3ret 2010-09-10 21:15:45