正如我在评论中提到的,当您尝试处理合并时,情况会完全不同。但是要解决您现在提出的问题。使用Red Black Tree 非常简单,我习惯将其称为RBTree。
有成千上万的RBTree 实现,因此您可以选择一个适合您的语言。我只使用类似 python 的伪代码提供我的方式到allocate 内存。 (就像我说的,如果你在释放内存时试图弄清楚,这是一个不同的问题。)
RB树:
key:0 的个数。
value:连续0的第一个位置。
所以在你的情况下,你的问题应该被初始化为:
rbt=new RBTree()
rbt.insert(2, 0)
rbt.insert(6, 3)
rbt.insert(3, 12)
rbt.insert(4, 18)
如果我数错了,请原谅我。
当你想分配一块内存时:
func alloc(num_of_chunks):
# try to find the key-value-pair that is the min one that satisfy: chunk.key >= num_of_chunks
chunk=rbt.find_ceil(num_of_chunks)
if chunk is Nil: raise NotFound
ret=chunk.value
# may locate some chunks that have bigger size than required.
if chunk.key>num_of_chunks:
rbt.insert(chunk.key-num_of_chunks, chunk.value+num_of_chunks)
return ret
所以要维护树。
使用RBTree的优势:
速度很快。我在评论中提出的线性搜索是O(n),但是使用RBTree,它会缩小到O(lg n),这意味着它更具可扩展性。
易于维护。有数千个实施良好的库可以满足您的不同需求。
1234563合并。
更新
这个答案似乎涉及动态内存分配,可能会引入母鸡问题,实际上并非如此。
如果你知道一个块没有被分配,它必须是未使用的。因此,RBTree 的数据可以存储在未使用的块中,这意味着元数据实际上分布在内存空间中。因此在 C 中,此类问题中的节点可能是:
struct node {
int length; // key
struct node *left, *right;
}
在块的第一个字节中。
所以你要做的就是记住root。
struct node *root;
// your code should operate on rootp, since rotation on RBTree may have root changed.
// all interfaces related should all receive struct node ** type.
struct node **rootp = &root;
“那么值呢?你没有定义一个字段来存储块的地址。”
是的,我已经定义了。由于数据本身存储在chunk中,所以struct node的地址就是chunk的地址。
所以通过这种方式,您可以避免动态内存分配,而且,我似乎没有回答您如何找到合适的位序列......但我认为通过这种方式,您可以管理您的内存分配更好。