Text 向文本添加样式的最有效数据结构

Text 向文本添加样式的最有效数据结构,text,data-structures,text-editor,styling,styledtext,Text,Data Structures,Text Editor,Styling,Styledtext,我正在寻找最好的数据结构来为文本添加样式(比如在文本编辑器中)。结构应允许以下操作: 在绝对位置X快速查找所有样式 在任意位置快速插入文本(必须移动该位置后的样式) 文本的每个位置都必须支持任意数量的样式(重叠) 我考虑过包含文本范围的列表/数组,但它们不允许在不重新计算插入点后所有样式的位置的情况下快速插入 具有相对偏移量的树结构支持#2,但当我向文本添加大量样式时,树将快速退化 还有其他选择吗?我从来没有开发过编辑器,但是这个怎么样: 我相信可以扩展用于存储文本字符的方案,当然这取决于您的实

我正在寻找最好的数据结构来为文本添加样式(比如在文本编辑器中)。结构应允许以下操作:

  • 在绝对位置X快速查找所有样式
  • 在任意位置快速插入文本(必须移动该位置后的样式)
  • 文本的每个位置都必须支持任意数量的样式(重叠)
  • 我考虑过包含文本范围的列表/数组,但它们不允许在不重新计算插入点后所有样式的位置的情况下快速插入

    具有相对偏移量的树结构支持#2,但当我向文本添加大量样式时,树将快速退化


    还有其他选择吗?

    我从来没有开发过编辑器,但是这个怎么样:

    我相信可以扩展用于存储文本字符的方案,当然这取决于您的实现细节(语言、工具包等)以及您的性能和资源使用要求

    我不想对样式使用单独的数据结构,而是更希望每个字符都有一个引用,并指向带有适用字符的数组或列表。具有相同样式集的字符可以指向相同的数组或列表,这样就可以共享一个数组或列表

    字符的插入和删除不会影响样式本身,除了更改对它们的引用数量,这可以通过一点引用计数来处理

    根据您的编程语言,您甚至可以通过指向列表的一半来压缩一些内容,尽管这样做的额外簿记实际上可能会使其效率更低

    这个建议的主要问题是内存使用。在用C编写的ASCII编辑器中,由于结构对齐填充,在64位系统中,将指针与每个字符绑定会将其有效内存使用量从1字节提高到12字节

    我将考虑将文本分解成小的可变大小的块,这样可以有效地压缩指针。例如,一个32个字符的块在C中可能是这样的:

    struct _BLK_ {
        unsigned char size;
        unsigned int styles;
        char content[];
    }
    
    有趣的部分是结构变量部分的元数据处理,它包含存储的文本和任何样式指针。size元素将指示字符数。styles整数(因此为32个字符限制)将被视为一组32个1位字段,每个字段指示字符是否有自己的样式指针,或者是否应使用与前一个字符相同的样式。这样,一个具有单个样式的32个字符的块将只具有大小字符、样式掩码和单个指针以及任何填充字节的额外开销。在这样的小数组中插入和删除字符应该非常快

    至于文本存储本身,树听起来是个好主意。也许是一个二叉树,其中每个节点值都是子节点值的总和,叶节点最终指向文本块,其大小作为节点值?根节点值是文本的总大小,理想情况下,每个子树包含文本的一半。不过,您仍然需要自动平衡它,有时还需要合并半个空文本块

    如果你错过了,我不是树木专家:-)

    编辑:

    显然,我建议的是此数据结构的修改版本:

    如本文所述:

    编辑2:

    建议的数据结构中的删除应该相对较快,因为它可以归结为数组中的字节移位和样式掩码上的一些按位操作。插入几乎是一样的,除非一个块填满了。在每个块内保留一些空间(即样式掩码中的一些位)以允许将来直接在块中插入,而不必为相对少量的新文本更改树本身,这可能是有意义的

    将字符和样式捆绑在这样的块中的另一个优点是,其固有的数据局部性应允许比其他替代方案更有效地使用CPU缓存,从而在一定程度上提高处理速度


    不过,与任何复杂的数据结构一样,您可能需要使用具有代表性的测试用例进行评测,或者使用自适应算法来确定其操作的最佳参数(块大小、任何保留空间等)。

    您决定了文本本身将如何存储吗?文本使用的任何结构都必须有效地处理插入/删除,因此,可以通过让文本指向样式而不是相反的方式来扩展。类似于为每个字符附带一个指向适用样式的数组/列表的指针。您应该能够在字符之间共享样式和数组,并且您可能能够共享指针本身。@thkala:请将其作为答案发布,以便我可以发表评论。+1了解压缩样式的想法。我看过rope结构,在你需要保存样式之前它很好。样式的主要问题是你需要能够有效地回答这个问题:哪些样式在文本中的位置X处处于活动状态?此外,插入/删除文本时,样式管理应该简单(拆分样式、合并样式、删除样式)。大多数编辑器使用树结构(如间隔树:),但如果在某个位置添加字符,则需要重新计算文本末尾的所有间隔。@Aaron Digulla:是的,如果不将样式捆绑在一起,则保持样式与文本同步可能会很混乱。另一方面,与我提出的方法类似的方法需要(更多?)更多的内存来存储样式变化相对较少的文本,但它们访问和修改速度很快,而且随着文本样式变得更加复杂,它们甚至可能变得更具内存效率。