【发布时间】:2018-03-22 01:11:42
【问题描述】:
我正在阅读 Joaquin Cuenca Abela 的 this great article。他谈到使用红黑树来实现一块表,而不是双向链表。
我在理解这可能与正在发生变化的缓冲区有什么关系时遇到了一些麻烦。例如,取这两个缓冲区(原始,追加):
Hello!\0 Original
y Append
假设棋子表如下所示:
buffer start length
original 0 2
original 5 2
append 0 1
我们应该得到:
Hey!\0
使用双向链表,可以这样实现:
------------------ ------------------- ----------------
Buffer = ORIGINAL| |Buffer = ORIGINAL| |Buffer = APPEND
Start = 0 |<--|Start = 5 |<--|Start = 0
Length = 2 | |Length = 2 | |Length = 1
Next = 0x01 |-->|Next = 0x02 |-->|Next = NULL
Previous = NULL | |Previous = 0x01 | |Previous = 0x01
------------------ ------------------- ----------------
如果文件最初是作为 char 数组或其他内容加载的,那么在编辑后运行起来似乎非常简单且快速。另一方面,据我了解,红黑树看起来像这样:
------------------
size = 2
size_left = 1
size_right = 2
colour = black
------------------
/ \
/ \
/ \
---------------- ----------------
size = 1 size = 2
size_left = 0 size_left = 0
size_right = 0 size_right = 0
colour = red colour = red
---------------- ----------------
/ \ / \
/ \ / \
NULL NULL NULL NULL
我没有看到在编辑后重新绘制文档其余部分的明确方法。当然,插入/删除/查找将块添加到树中会更快。但我错过了如何构建已编辑的缓冲区以供查看。
我错过了什么?如果我有一个编辑器,并且我删除/插入了一大块文本,我将如何遍历树以重新绘制缓冲区并正确反映此编辑?而且,这会比链表提供的 O(n) 时间复杂度更快吗?
【问题讨论】:
-
@rici 我想我主要了解树是如何工作的,但我只是不明白如何在这种特定的上下文中(重新绘制缓冲区以反映更改)它具有优势。维基百科确实有很好的解释,但它没有涵盖这个主题。我找不到任何其他资源可以回答我的问题,所以我在这里问了
-
我理解这方面;我不明白的是如何通过遍历树来反映所做的更改。使用双向链表,非常清晰;每个节点指向原始和附加缓冲区中的一个点,并且通过保持每个条目的长度的运行总和,对节点所做的任何更改都可以通过遍历列表来反映:即,通过选择打印文本片段来自原始缓冲区或附加缓冲区的某个位置和长度。对于树,我不清楚这是如何完成的。但是,我确实理解轮换/必须“修复”树。
-
我认为我最大的问题是努力全面思考一个例子。考虑到存储在树中的信息(在上面的示例或其他示例中),看看我如何构建一个新的缓冲区会很有帮助。从概念上讲,在我看来,使用链表构造缓冲区需要 O(N)。但是等效的操作不会对树采取 O(NlogN) 吗?因为,对于 N 件,需要 O(logN) 来检索其信息?
-
在 cmets 交流的基础上,我试图写一个答案来解决你的问题。我希望它有所帮助。
标签: algorithm binary-tree text-editor red-black-tree