我已经给了很多想法,但实际上并没有想出一些东西。
假设我想要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
我会创建两个索引数组,一个用于列,一个用于行。所以对你的数据
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)
,这里只需用最后一个替换要删除的列/行,然后从索引数组中删除索引。
只是添加到马丁努斯和迈克的答案:你需要的是,实质上是旋转,这是他们的建议,并且几乎任何涉及矩阵的数值算法都使用了一种非常着名的技术。例如,您可以快速搜索“使用部分旋转进行LU分解”和“使用完全旋转进行LU分解”。存储排列的附加矢量称为“枢轴”。
如果我遇到了这个问题,我会创建行和列重映射向量。例如。为了排序行,我确定行顺序正常,但不是复制行,我只是更改行重新映射向量。
它看起来像这样:
// 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]];
附:一个小的优化是在rowMapping
中存储指针而不是索引。这会让你做T value = rowMapping[row][colMapping[col]];
,但是,每次data
的尺寸发生变化时你都必须重新计算指针,这可能容易出错。
您可以使用哈希表并插入(i,j) - > node其中(i,j)是包含2个整数的2元组。您可以编写自己的自定义类来定义Equals方法和GetHash()方法......或者Python免费提供给您。
现在......究竟是什么意思 - 按行或列排序?请举个价值观的例子!
也许是为它创建一个小型数据库?
数据库排序算法可能比重新发明轮子更好。 MySql会这样做。为了获得性能,可以在内存中创建表。然后,您可以将列索引为常规表,并让数据库引擎执行脏作业(排序等)。然后你就收获了结果。