Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.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 在3D数组中搜索满足某个谓词的最近点_Algorithm_Search_Multidimensional Array - Fatal编程技术网

Algorithm 在3D数组中搜索满足某个谓词的最近点

Algorithm 在3D数组中搜索满足某个谓词的最近点,algorithm,search,multidimensional-array,Algorithm,Search,Multidimensional Array,我正在寻找一种枚举算法,以搜索围绕给定起点的3D数组“球体” 给定一个大小为NxNxN的数组a,其中对于某些k,每个N都是2^k,以及该数组中的一个点p。我正在寻找的算法应该执行以下操作:如果a[p]满足某个谓词,则该算法停止并返回p。否则将选中下一个点q,其中q是阵列中最接近p且尚未访问的另一个点。如果两者都不匹配,则检查下一个q',以此类推,直到在最坏的情况下搜索了整个数组 通过这里的“最近点”,完美的解决方案是点q,它与p的欧氏距离最小。由于只需要考虑离散点,也许一些聪明的枚举算法可以实现

我正在寻找一种枚举算法,以搜索围绕给定起点的3D数组“球体”

给定一个大小为
NxNxN
的数组
a
,其中对于某些
k
,每个
N
都是
2^k
,以及该数组中的一个点
p
。我正在寻找的算法应该执行以下操作:如果
a[p]
满足某个谓词,则该算法停止并返回
p
。否则将选中下一个点
q
,其中
q
是阵列中最接近
p
且尚未访问的另一个点。如果两者都不匹配,则检查下一个
q'
,以此类推,直到在最坏的情况下搜索了整个数组

通过这里的“最近点”,完美的解决方案是点
q
,它与
p
的欧氏距离最小。由于只需要考虑离散点,也许一些聪明的枚举算法可以实现这一点。然而,如果这变得太复杂,曼哈顿的最小距离也可以。如果有几个最近的点,下一个应该考虑哪一个并不重要


已经有一个算法可以用于此任务了吗?

这是一个简单算法的伪代码,该算法将搜索越来越大的半径球形外壳,直到找到一个点或耗尽阵列。假设
条件
返回true或false,并且可以访问正在测试的x、y、z坐标和数组本身,对于越界坐标返回false(而不是分解):

def find_from_center(center, max_radius, condition) returns a point
  let radius = 0
  while radius < max_radius,
     let point = find_in_spherical_husk(center, radius, condition)
     if (point != null) return point
     radius ++
  return null
这将是我们对外壳的操作定义。我们可以在O(n^3)中迭代整个3D数组来寻找这些,但这在时间上会非常昂贵。更好的伪代码如下所示:

def find_in_spherical_husk(center, radius, condition)
   let z = center.z - radius // current slice height
   let r = 0 // current circle radius; maxes at equator, then decreases
   while z <= center + radius,
     let z_center = (z, center.x, point.y)  
     let point = find_in_z_circle(z_center, r)
     if (point != null) return point
     // prepare for next z-sliced cirle
     z ++
     r = sqrt(radius*radius - (z-center.z)*(z-center.z)) 
def在球形外壳中查找(中心、半径、条件)
设z=中心。z-半径//当前切片高度
设r=0//当前圆半径;赤道处最大,然后减小

当z时,您可以搜索增加的平方距离,这样您就不会错过任何一点。这段python代码应该清楚地说明:

导入数学
进口itertools
#计算特定距离处的所有点。

#坐标约束:z您正在混合任务和解决方案。而你确定的解决方案部分并不适合这个问题。谁说按一个细胞的步骤走你会找到最近的“好”细胞?相反,下一个距离层的单元大部分将被分离。@fafl:我看了R-tres,但我不知道如何使用它来找到给定的
p
的最近的
q
。首先,在R-树中搜索确定某个分支,然后将在该分支中找到最近的点,如果您选择了错误的分支,则不一定是所有分支中的最近点。如果您不使用距离,而是使用它们的平方,则层内搜索将更加简单。平方是一个增长函数,所以你不会损失任何东西。@Gangnus-true,但总的来说会节省一点时间。最大的好处是,它避免了潜在的精度相关的错误,因为它坚持整数,当然是无损的。这是因为我使用这种方法进行距离检查已经有39年了。@tucuxi:谢谢,到目前为止,你的算法似乎使用了一个更简单的“
find_in_z_square
”函数,该函数检查点是否位于围绕中心的正方形表面上,而不是圆上。我有点担心,如果使用像Bresenham这样的圆算法,两个相邻半径之间可能会遗漏一些点。这种算法会发生吗?@siracusa不,不应该有这种担心。只要您真正检查满足其距离为
=r
的点(或者,为了避免浮点和平方根,它们的距离平方在r^2和(r+1)^2之间-正如Gangus所指出的),点就不可能丢失或重复计数。Bresenham只是简单地避免了额外的数学运算,但IIRC通过将错误项严格保持在所需的边界之间来做到这一点。
def find_in_spherical_husk(center, radius, condition)
   let z = center.z - radius // current slice height
   let r = 0 // current circle radius; maxes at equator, then decreases
   while z <= center + radius,
     let z_center = (z, center.x, point.y)  
     let point = find_in_z_circle(z_center, r)
     if (point != null) return point
     // prepare for next z-sliced cirle
     z ++
     r = sqrt(radius*radius - (z-center.z)*(z-center.z))