用于访问N(未知)维度矩阵中的所有点的算法

时间:2010-08-24 19:12:47

标签: c# algorithm c#-3.0 matrix traversal

我有一个多维矩阵,可以有任意数量的维度大于1。寻找一种可以访问矩阵中每个点的有效算法。

有关代码的一些信息: 矩阵具有值访问器(尽管这些并不是真正相关的)。

object value = matrixInstance.GetValue(int[] point);   
matrixInstance.SetValue(object value, int[] point);  

注意:参数 point 是索引数组,必须与维度匹配或抛出异常。

有关矩阵结构的信息可以通过以下方式获得:

int numDims = matrixInstance.Rank; //# dimensions
int sizeDim = matrix.getRankSize(int index); // length of specified dimension

我想使用相对有效的算法迭代矩阵的所有可能点。

例如,在2x3 2D矩阵中,将访问以下六个点:
[0,0] [0,1] [0,2] [1,0] [1,1] [1,2]

算法必须达到N维:2,3,4等。为了提高效率,我最终会使用C# iterator来返回积分。

4 个答案:

答案 0 :(得分:4)

您可以在树上查看一个树,该树的所有值都在树叶处:

Illustration

是矩阵

[0,0] = 'A'
[0,1] = 'B'
[1,0] = 'C'
[1,1] = 'D'

只需应用任何众所周知的树遍历解决方案。


这是一个递归解决方案(未经测试):

IEnumerable<Point> GetPoints(Matrix matrix, int[] indexes)
{
    if (indexes.Length == matrix.Rank)
    {
        yield return matrix.GetValue(indexes);
    }
    else
    {
        for (int i = 0; i < matrix.GetRankSize(indexes.Length); i++)
        {
            foreach (var point in
                GetPoints(matrix, indexes.Concat(new int[] { i }).ToArray())
            {
                yield return point;
            }
        }
    }
}

将此转换为使用显式堆栈的迭代版本应该是相当简单的。

答案 1 :(得分:1)

如果您可以在运行时为每个维度生成索引值的集合,则可以使用Eric Lippert's LINQ snippet生成索引值的所有组合。

Eric制作所有组合集合的方法:

static IEnumerable<IEnumerable<T>> CartesianProduct<T>(this IEnumerable<IEnumerable<T>> sequences) 
{ 
  IEnumerable<IEnumerable<T>> emptyProduct = new[] { Enumerable.Empty<T>() }; 
  return sequences.Aggregate( 
    emptyProduct, 
    (accumulator, sequence) =>  
      from accseq in accumulator  
      from item in sequence  
      select accseq.Concat(new[] {item}));                
}

所以,对于你的2x3例子,

int [ , ] dimensions= { { 0, 1}, { 0, 1, 2 } } ;
var allMatrixCells = CartesianProduct<int>(dimensions);

foreach(var cellLocation in allMatrixCells )
{
 ...
}

答案 2 :(得分:1)

只需递归迭代每个维度。例如,第一次调用迭代第一个维度的每个值,调用自身迭代第二个维度的每个值,依此类推,无论你有多少维度。然后,基本情况(当没有更多维度时)是返回相关单元格中的值,而不是再次递归。

答案 3 :(得分:0)

您可以使用混合基数表示,请参阅例如http://en.wikipedia.org/wiki/Mixed_radix

例如,如果您有4个长度为4,3,2,7的维度,然后对应于索引a,b,c,d我们有数字a + 4 *(b + 3 *(c + 2 *) d))。从中恢复指数 数字n就像得到十进制数字一样,除了基数不同,即 a = n%4; n / = 4; b = n%3; n / = 3; c = n%2; N / = 2; d = n。

所以你会有一个for循环(在这种情况下为n = 0..4 * 3 * 2 * 7-1),其中索引可以 从上面的n中恢复。

然而,也许所有这些划分和模数都意味着这不是那么有效。