在更多地考虑了行/列插入/删除的问题之后,我想出了一些看起来很有希望的东西。
首先,创建并维护 2 个已排序的数据结构(例如搜索树),其中包含所有水平和所有具有至少一个非空单元格的垂直索引。
对于此表:
ABCDE
1
2*
3 % #
4
5 $
你会有:
- A,B,D,E - 使用的水平索引
- 2,3,5 - 使用的垂直索引
将这些 A、B、D、E、2、3、5 索引值存储在上述 2 个结构中的某种节点内,这样您就可以知道节点在内存中的地址将某些东西链接到它(同样,树节点非常适合)。
在每个单元格(非空)中,都有一对指向索引节点的链接描述其位置(我使用 & 来表示对节点的链接/引用):
- *: &2,&A
- %: &3,&B
- #: &3,&E
- $: &5,&D
这足以定义一个表。
现在,我们如何处理行/列插入?我们将新的行/列索引插入到相应的(水平或垂直)索引数据结构中,并在其之后更新索引值(=向右或向下)。然后我们为这个新的行/列(如果有的话)添加新的单元格,并将它们链接到适当的索引节点。
例如,让我们在第 3 行和第 4 行之间插入一行,并在 4C 处添加一个带有 @ 的单元格(在新行中):
ABCDE
1
2*
3 % #
4 @ <- new row 4
5 <- used to be row 4
6 $ <- used to be row 5
您的索引结构现在是:
- A,B,C(new),D,E - 使用的水平索引
- 2,3,4(新),6(以前是 5) - 使用的垂直索引
单元格现在链接到索引节点,如下所示:
- *: &2,&A - 和之前一样
- %: &3,&B - 和之前一样
- #: &3,&E - 和以前一样
- @: &4,&C - 链接到新索引节点 4 和 C 的新单元格
- $: &6,&D - 曾经是 &5,&D
但是看看 $ 单元格。它仍然指向与以前相同的两个物理节点,只是垂直/行节点现在包含索引 6 而不是索引 5。
如果 $ 单元格下方有 100 个单元格节点,例如只占用 5 个非空行,则您只需要更新行/垂直索引数据结构中的 5 个索引,而不是 100 个。
您可以以类似的方式删除行和列。
现在,为了使这一切变得有用,您还需要能够通过其坐标定位每个单元格。
为此,您可以创建另一个排序的数据结构(同样,可能是搜索树),其中每个键是索引节点地址的组合,值是单元格数据的位置(或单元格数据本身)。
这样,如果您想到达单元格 3B,您可以在索引数据结构中找到 3 和 B 的节点,获取它们的地址 &3 和 &B,将它们组合成 &3*2 32 +&B 并将其用作定位的键我刚刚定义的第三个数据结构中的 % 单元格。(注意:2 32实际上是 2位指针大小,可能因系统而异。)
无论其他单元格发生什么情况,% 单元格链接中的地址 &3 和 &B 将保持不变,即使 % 单元格的索引从 3B 更改为其他值。
您可以轻松地在此基础上开发迭代。
合并应该也是可行的,但我没有关注它。