Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/symfony/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 用于插入超长字符数组的高效数据结构_Arrays_String_Algorithm_Data Structures - Fatal编程技术网

Arrays 用于插入超长字符数组的高效数据结构

Arrays 用于插入超长字符数组的高效数据结构,arrays,string,algorithm,data-structures,Arrays,String,Algorithm,Data Structures,什么样的数据结构和/或算法适合实现带有插入的字符数组。典型的工作负载是几个“随机”读取的循环,然后是一个“随机”插入。该阵列将是巨大的,大约为千兆字节 编辑:在极端情况下,算法需要能够通过单字节插入有效地构建千兆字节字符串。我建议您使用数据结构。SGI C++ STL提供了一个典型的扩展名: 。如果需要重新实现此数据结构,最好咨询他们的。,因为此数据结构应允许各种极端情况(如插入长字符串或大量单个字符,表示非常长的数组,可能内存受限),单一的已知数据结构不太可能满足所有需求 你可以考虑这两个数据

什么样的数据结构和/或算法适合实现带有插入的字符数组。典型的工作负载是几个“随机”读取的循环,然后是一个“随机”插入。该阵列将是巨大的,大约为千兆字节


编辑:在极端情况下,算法需要能够通过单字节插入有效地构建千兆字节字符串。

我建议您使用数据结构。SGI C++ STL提供了一个典型的扩展名:<代码> <代码>。如果需要重新实现此数据结构,最好咨询他们的。

,因为此数据结构应允许各种极端情况(如插入长字符串或大量单个字符,表示非常长的数组,可能内存受限),单一的已知数据结构不太可能满足所有需求

你可以考虑这两个数据结构:

  • 。如果插入的字符串相对较长,则效果良好
  • 。它不存在大量单字符(或短字符串)插入的问题,只需要很少的额外内存,允许非常快速的随机读取。但是对于插入,它的时间复杂度非常差:O(sqrt(n))(如果我们允许更多的额外内存,这可以得到改进)。当插入长绳时,它不如绳子
  • 或者,您可以使用基于rope或分层向量的定制数据结构

    如果您希望有太多的小插入,并且希望避免太多的绳索断裂,那么可以使用数组树;当数组较短时插入到数组中间;但若数组的大小增长到某个极限,下一次插入应该将其拆分,就像在rope中一样。树节点引用的数组应该相当大(大约1000字节或更大),以便在访问树节点时在非常昂贵的缓存未命中(因此我们应该尽量减少不适合缓存的节点数量)和稍微便宜的memmove之间获得更好的平衡

    这些数组最合适的内存分配方案如下:当数组不适合其分配的空间时,将其分成两个相等的部分,为每一半分配固定数量的字节(如2000),然后将每一半复制到分配空间的中间。在靠近数组末尾插入字符时,将尾部字符向右移动。在靠近开头插入字符时,将前面的字符向左移动。所以memmove的平均长度只有平均数组长度的1/4。两个相邻的分配空间可以在它们之间共享未使用的字节,所以我们只需要在一个块的字节即将覆盖另一个块的已使用字节时进行拆分。这种方法很简单,但需要一些额外的空间来允许阵列增长。我们可以使用一些通用分配器只获取阵列实际使用的空间(或允许非常有限的增长空间),但它的速度要慢得多,很可能会导致内存碎片,甚至导致大量未使用的内存。可能更好的节省内存的方法是使用几个固定的分配空间(如1500、1700、2000),并保留一定数量(实验确定)的每种大小的块。另一种节省内存的方法是(而不是将一个2000字节数组拆分为两个1000字节数组)合并两个相邻数组(如2000+1600),然后将结果拆分为三个数组(1200+1200+1200)

    您提到了“将位打包在一起”以减少RAM使用。对于这样的数据结构(如果您的数据是可压缩的),这并非不可能。实际上,在不牺牲太多性能的情况下,这里可以使用两种压缩算法:哈夫曼编码或LZ4。对于哈夫曼编码,您需要一个静态频率表(预先计算)。对于读取,您只需要解码平均数组大小的1/4,然后到达适当的位置加上要读取的字符串长度。对于插入,您需要解码相同的平均数组大小的1/4,然后移动相同大小的位流,然后对插入的字符串进行编码。LZ4不需要处理比特流,只使用整个字节;也许增加数组的大小以获得更好的压缩是值得的

    可以优化分层向量,使其更便于缓存。向每个块添加大约100-200字节的保留空间。每次插入memmove字节到这个空间。只有在没有空间容纳下一个memmove之后,才开始在块之间交换数据(不是像原始数据结构那样使用单个字节,而是一次交换100-200字节)


    为了提高O(Sqt(n))插入时间,将分层向量视为TIE的特例,只有2个级别。我们可以再增加一个级别。然后(插入后),当我们到达第二级块的末尾时,我们可以停止块间数据交换,分配额外的第一级块,并在那里放置额外的字节。当一个或多个附加块被填满时,我们可以继续在第三级块(trie的根)上进行数据交换。理论上,这可以扩展到日志(n)级别,以保证O(日志(n))单字符插入和读取。但在实践中,可能3或4个级别是更好的选择,因此我们有O(n1/3)或O(n1/4)摊销插入复杂性。

    。我了解rope,但我感觉它们不会很好地处理这种情况。想象一下,一个千兆字节有100万个单字节插入。绳子不需要100米长的树吗?没错。绳子并不总是最好的选择。在某些情况下,最好发明一种自定义数据结构(很可能与rope非常相似)。如果您希望有太多的小插入,并且希望避免太多的拆分,那么仍然可以使用数组树;当数组较短时插入到数组中间;但若数组的大小增长到某个极限,那个么下一个insert应该将其拆分,就像在rope中一样。谢谢,我正在考虑类似的结构。你知道有多少字节的memmove比二叉树的house-keeping还要快吗