从中间向外循环数组的算法?
Posted
技术标签:
【中文标题】从中间向外循环数组的算法?【英文标题】:Algorithm to loop over an array from the middle outwards? 【发布时间】:2011-07-26 23:52:53 【问题描述】:我正在研究一种分而治之的算法(事实上,一种对多个输入点进行曲线拟合的算法)。对于“除法”部分,我需要计算每个点的误差项,如果误差超过给定阈值,我希望在该点分割曲线并分别处理输入的左右部分。一个简单的循环就可以了。但从当前部分的中间开始向外工作对我来说是有利的。 (澄清一下:如果我确实找到了一个误差太大的点,我会递归调用并为左右部分生成单独的曲线 - 如果所有点都在阈值内,那么我的曲线适合并返回)。
经过一番摸索,我想出了这个(点在一个数组中,当前部分从startIndex
到endIndex
包括在内):
int steps = (endIndex+1-startIndex);
int i = (startIndex+endIndex)>>1;
int stepdir = 1;
for(int q=0; q<steps; q++, i+=stepdir*q, stepdir=-stepdir)
// test point i here and return early if error exceeds threshold
换句话说,从中间附近开始,向前走一个索引,向后走两个,向前走三,向后走四......它有效,我确信它是有效的,但我觉得应该有一种更清洁的方式为此,特别是,我最终不得不检查 Java 语言规范,以确保 for update 表达式中的语句确实按顺序计算(尽管 , 不是 C/C++ 中的序列运算符)。
感谢任何想法。有没有更清洁的方法?
【问题讨论】:
您是否将此循环用作递归函数的一部分?即拆分并在每次拆分时递归调用。 是的...已编辑问题以澄清。最终结果是一系列“简单”曲线在某些源点处连接,并且与它们之间的源点“足够接近”。 【参考方案1】:恕我直言,这将更具可读性
for (int q=0; q < steps; q++)
int index = i + ( q% 2 == 0 ? q/2 : -(q/2+1)); //index lookup here
【讨论】:
同意。这使得每个索引只被访问一次并且整个数组都被覆盖的情况变得更加明显。谢谢。 那不是访问零两次吗? 如果 q == 1 它将是 index = i + -(0+1)。如果 q == 2,它将是 index = i + (1)。我将在示例中添加括号以使其更清晰【参考方案2】:如果您的超额错误检查器很简单(例如,函数调用),那么最清楚的就是编写:
int mid = npoints / 2;
for (int i = 0; i <= mid; i++)
if( excess_error(mid + i + 1) )
// divide at mid + i + 1
else if excess_error(mid - i)
// divide at mid - i
同样,“在 xyz 处除”代码应该是一个函数调用,否则您会得到剪切和粘贴的代码。
(我没有仔细考虑过极端情况和非一个错误,所以当 i==mid 时要小心,但你明白了。)
【讨论】:
一旦我发现一个太大的错误,我就会跳出循环并递归两半......所以'divide'部分几乎是设置一个分割点变量并突破的循环。我确实存储了错误计算的结果以供以后报告;所以绝对值得指出的是,通用行为应该在函数调用中实现。 好的,所以保存点和中断也很简单,代码重复量几乎与函数调用一样少。【参考方案3】:对于需要从任意点向外搜索的任何人来说,这是一个更通用的解决方案(在此示例中,单元格 [6]
在长度为 7 的数组中)。
int arraySize = 7;
int start = 6;
for (int i=0; i < arraySize; i++)
int index = (start+((i%2==0)?i/2:arraySize-(i+1)/2))%arraySize;
print(index+",");
exit();
打印 6,5,0,4,1,3,2,
【讨论】:
以上是关于从中间向外循环数组的算法?的主要内容,如果未能解决你的问题,请参考以下文章