【问题标题】:design a data structure to hold large amount of data设计一个数据结构来保存大量数据
【发布时间】:2013-08-09 17:55:00
【问题描述】:

我在一次采访中被问到以下问题,我无法解决任何问题,这将非常有帮助。

我有 100 个文件,每个文件大小为 10 MB,每个文件的内容都是一些字符串映射到整数值。

string_key=整数值

 a=5
 ba=7
 cab=10 etc.. 

可用的物理 RAM 空间为 25 MB。如何设计数据结构:

For any duplicate string_key, the integer values can be added
Display the string_key=integer value sorted in a alphabetical format

约束:

All the entries of a file could be unique. All of the 10*1000MB of data could be unique string_key mapping to an integer value. 

解决方案 1:

我正在考虑一个接一个地加载每个文件并将信息存储在哈希图中,但是这个哈希图会非常大,如果所有文件都包含唯一数据,则 RAM 中没有足够的可用内存.

还有其他想法吗?

使用 noSqldb 不是一个选项。

【问题讨论】:

  • 我不知道这是否是他们正在寻找的答案,但 1) 对 100 个文件中的每一个文件进行排序,一次一个。将排序后的输出写入另外 100 个文件。 2)做100个文件匹配/合并,添加重复key整数值,并显示字符串key和整数值。
  • @gilbert le blanc 我同意第 1 步,当您在第一次迭代时只允许加载 2.5 个文件时,您将如何实现第 2 步?并且后续步骤中的文件数量要少得多。另外,当所有文件都具有唯一的字符串键值对时,最坏的情况会怎样
  • @bhava:您一次只在内存中的 100 个排序文件中的每个文件中保留两行。您在阅读文件时打印。这称为磁盘匹配/合并。这是我们 40 年前必须进行的处理。

标签: data-structures


【解决方案1】:

这是我的尝试。基本上这个想法是使用一系列小的二叉树来保存排序的数据,动态创建并将它们保存到磁盘以节省内存,并使用链表对树本身进行排序。

手摇版:

根据条目的键创建按字母顺序排序的二叉树。每个条目都有一个键和一个值。作为一个属性,每棵树都有它的第一个和最后一个键的名称。我们分别加载每个文件,并逐行向树中插入一个条目,它会自动对其进行排序。当树的内容大小达到 10 mb 时,我们将树分成两棵各 5 mb 的树。我们将这两棵树保存到磁盘中。为了跟踪我们的树,我们保留了一组树及其名称/位置以及它们的第一个和最后一个属性的名称。从现在开始,对于文件 N 中的每一行,我们使用我们的列表来定位适当的树以将其插入,将该树加载到内存中,并执行必要的操作。我们继续这个过程,直到我们到达终点。

使用此方法,加载到内存中的最大数据量将不超过 25 mb。总是加载一个文件N(10mb),加载一个树(最多 10mb),以及一个树的数组/列表(希望不会超过 5mb)。

稍微严谨一点的算法:

  1. 初始化一个已排序的二叉树B,其条目是(key, value) 元组,根据条目的属性key 进行排序,并具有name, size, first_key, last_key 属性,其中name 是任意唯一字符串,@987654326 @ 是以字节为单位的大小。

  2. 初始化一个排序链表L,其条目是(tree_name, first_key)形式的元组,基于条目的属性first_key排序。这是我们的树列表。将元组(B.name, B.first_key) 添加到L

  3. 假设文件名为file1, file2, ..., file100,我们继续执行以下算法,该算法是用与python 非常相似的伪代码编写的。 (我希望我在这里使用的未声明的函数是不言自明的)

    for i in [1..100]:
        f = open("file" + i)   # 10 mb into memory
        for line in file:
            (key, value) = separate_line(line)
    
            if key < B.first_key or key > B.last_key:
                B = find_correct_tree(L, key)
    
            if key.size + value.size + B.size > 10MB:
                (A, B) = B.split()     # supp A is assigned a random name and B keeps its name
                L.add(A.name, A.first_key)
                if key < B.first_key:
                    save_to_disk(B)
                    B = A      # 5 mb out of memory
                else:
                    save_to_disk(A)
    
            B.add(key)
    save_to_disk(B)
    

然后我们只遍历列表并打印出每个关联的树:

    for (tree_name, _) in L:
        load_from_disk(tree_name).print_in_order()

这有点不完整,例如要完成这项工作,您必须在每次first_key 更改时不断更新列表L;而且我还没有严格证明这在数学上使用了 25 mb。但我的直觉告诉我,这可能会奏效。也可能有比保持排序链表(可能是哈希表?)更有效的方法来对树进行排序。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-27
    • 2018-03-27
    • 1970-01-01
    • 2013-02-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多