最佳的2D数据结构

时间:2010-01-03 17:03:18

标签: c++ algorithm data-structures

我已经给了很多想法,但实际上还没有想出一些东西。

假设我想要X列的元素集合可以按任何列和O(m * n)下的任何行进行排序,还能够插入或删除O(m + n)或更少的行...有可能吗?

我想到的是一个链接网格,其中节点被插入到一个向量中,所以我有它们的索引,并索引第一行和列,以消除在任何一个方向遍历列表的必要性。用我的方法我已经实现了上述复杂性,但我只是想知道是否有可能通过一个非常数因子进一步减少它。

可排序性示例:

1 100 25 34
2 20  15 16
3 165 1  27

按第3行排序:

25 1 34 100
15 2 16 20
 1 3 27 165

按第1栏排序:

 1 3 27 165
15 2 16 20
25 1 34 100

5 个答案:

答案 0 :(得分:7)

我会创建两个索引数组,一个用于列,另一个用于行。所以对于你的数据

1 100 25 34
2 20  15 16
3 165 1  27   

您创建了两个数组:

  • cols = [0, 1, 2, 3]
  • rows = [0, 1, 2]

然后,当您想要按第3行对矩阵进行排序时,保持原始矩阵不变,但只需相应地更改indices数组:

  • cols = [2, 0, 3, 1]
  • rows = [0, 1, 2]

现在的诀窍是通过一个间接访问您的矩阵。因此,您无法通过m[x][y]访问它,而是通过m[cols[x]][rows[y]]访问它。在执行rows / cols数组的重新排序时,还必须使用m[cols[x]][rows[y]]

这种排序方式为O(n*log(n)),访问权限为O(1)

对于数据结构,我会使用一个包含指向另一个数组的链接的数组:

+-+
|0| -> [0 1 2 3 4]
|1| -> [0 1 2 3 4]
|2| -> [0 1 2 3 4]
+-+

要插入一行,只需将其插入最后一个位置,然后使用正确的位置相应地更新rows索引数组。例如。当rows[0, 1, 2]并且您想要将其插入前端时,行将变为[3, 0, 1, 2]。这样,行的插入就是O(n)

要插入列,您还要将其添加为最后一个元素,并相应地更新cols。插入列为O(m),行为O(n)

删除也是O(n)O(m),在这里您只需用最后一个删除要删除的列/行,然后从索引数组中删除索引。

答案 1 :(得分:2)

只是添加到马丁努斯和迈克的答案:你需要的是,实质上是旋转,这是他们的建议,以及几乎任何涉及矩阵的数值算法中使用的一种众所周知的技术。例如,您可以快速搜索“使用部分旋转进行LU分解”和“使用完全旋转进行LU分解”。存储排列的附加向量称为“枢轴”。

答案 2 :(得分:1)

如果我遇到了这个问题,我会创建行和列重映射向量。例如。为了对行进行排序,我会将行顺序确定为正常,但不是复制行,而只是更改行重映射向量。

它看起来像这样:

// These need to be set up elsewhere.
size_t nRows, nCols;
std::vector<T> data;

// Remapping vectors.  Initially a straight-through mapping.
std::vector<size_t> rowMapping(nRows), colMapping(nCols);
for(size_t y = 0; y < nRows; ++y)
    rowMapping[y] = y;
for(size_t x = 0; x < nCols; ++x)
    colMapping[x] = x;

// Then you read data(row, col) with
T value = data[rowMapping[row] * nCols + colMapping[col]];

P.S。一个小的优化是在rowMapping而不是索引中存储指针。这样您就可以T value = rowMapping[row][colMapping[col]];,但是,每次data的维度发生变化时,您都必须重新计算指针,这可能容易出错。

答案 3 :(得分:0)

您可以使用哈希表并插入(i,j) - &gt;节点其中(i,j)是包含2个整数的2元组。您可以编写自己的自定义类来定义Equals方法和GetHash()方法......或者Python免费为您提供。

现在......究竟是什么意思 - 按行或列排序?请举例说明值!

答案 4 :(得分:-2)

也许是为它创建一个小型数据库?

数据库排序算法可能比重新发明轮子更好。 MySql会这样做。为了获得性能,可以在内存中创建表。然后,您可以将列索引为常规表,并让数据库引擎执行脏作业(排序等)。然后你就收获了结果。