【发布时间】:2021-03-31 19:16:28
【问题描述】:
我正在使用Rope 来存储大量(GB)的文本。文本可以长达数千万行。
绳索本身在任何位置插入都非常快,并且在特定位置也可以快速获取角色。
但是,我如何获得特定行(在这种情况下为\n)的开始位置?例如,我如何获得第 15 行的开始位置?我可以看到几个选项。
- 没有任何额外的数据。每当你想说第 15 行时,你就遍历
Rope中的所有字符,找到换行符,当你到达第 15 行时,你就停下来。 - 将每行的
start和length存储在一个向量中。因此,您将拥有包含所有字符的Rope数据结构,然后是单独的std::vector<line>。line结构将仅包含 2 个字段;start和length。 Start 表示行在Rope内的起始位置,length 是行的长度。要获取第 15 行的开始位置,只需执行lines[14].start
问题:
#1 是一种可怕的方法。它非常慢,因为您必须遍历所有字符。
#2 也不好。虽然找到一行的开始位置非常快(O(1)),但每次插入一行时,都必须将所有行移到它前面,即O(N)。此外,存储这意味着对于您拥有的每一行,它会占用额外的 16 个字节的数据。 (假设 start 和 length 各有 8 个字节)。这意味着如果您有 13,000,000 行,它将占用 200MB 的额外内存。您可以使用链表,但这只会使访问变慢。
有没有更好更有效的方式来存储行位置以便快速访问和插入?(最好O(log(n)) 用于插入和访问行)
我正在考虑使用BST,更具体地说是RB-Tree,但我不完全确定这将如何工作。我看到 VSCode 做了 this 但用 PieceTable 代替。
任何帮助将不胜感激。
编辑:
@interjay 提供的答案似乎不错,但是如果 CR 和 LF 在 2 个叶节点之间拆分,我将如何处理 CRLF?
我还注意到ropey,它是Rope 的锈库。我想知道除了C++之外是否有类似的东西。
【问题讨论】:
-
您是否考虑将数据存储为表示线条的字符串向量?
-
@StefanHaustein 对于连接、子串、插入等操作,不会有绳索的 O(logn) 复杂度。相反,它们都需要线性时间。
标签: c++ data-structures text ropes