`
corvallis
  • 浏览: 5804 次
  • 性别: Icon_minigender_1
  • 来自: 上海
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

编辑器的数据结构

阅读更多

我从来没有实现过任何一个编辑器。但对于这么一个我们每天都使用的工具,如何高效的实现其内部结构是一个有趣的话题。首先, 一个高效的算法,以下几点是值得考虑的重点:

1. 所占的空间大小
2. 插入,删除的效率。

最直接的方法是使用一个数组, 数组的每一个成员对应一个相应的字符。这样不需要任何冗余空间,但是缺点也是显而易见的: 每次插入和删除都要进行数组拷贝的动作。

一个初步的提高, 我们是否能够在删除的时候不做这个拷贝动作, 而使用一个特殊的字符来取代。但是我们如何避免在插入时进行数组拷贝的动作呢。这个问题将直接导致两个常用的编辑器数据结构: Gap Buffer 和 Piece Table.

Gap Buffer:
就是在插入和删除的地方使用一个buffer,这个buffer可以看成在数组中的一个空白区域。这个区域随着编辑器光标的移动而移动。 实例如下:
                           

数组:我们使用  【                          】编辑器
                            ^
插入 “文本” 
我们使用文本【                         】编辑器 
                                    ^

   移动光标至文本之前:

  我们使用【                       】文本编辑器      

                     ^                          

        删除 “文本”:

     我们使用【                           】编辑器

       Gap Buffer 相应的数据结构也很简单:

public class 



GapBuffer


{
    private int 

startGapIndex;
    private int 

endGapIndex;
    private char

[FileSystemPageSize] textBuffer;
}

      GapBuffer 在光标移动的时候要进行数组拷贝。所以在文件比较大的时候,通常我们要使用一个链表的GapBuffer来存储文本。在上述的结构中,使用文件系统的page size 来构建buffer。当然我们还需要考虑,合并和扩展buffer的操作。

GapBuffer 的使用者包括Emacs.

Piece Table:

相比较Gap Buffer, Piece Table稍显复杂一些。Piece Table的实现由两个buffer组成,一个buffer是只读的,另一个buffer是可写的 (只能添加)。每一个Piece 代表了这两个buffer中的一块内存。每一个piece可以表示如下:

public class 



Piece


{
    private int 

bufferIndex;
    private int 

bufferOffset;
    private int 

length;
}

最终的文件可以看成所有piece的合在一起。示例如下:

buffer 0:【我们使用编辑器  】                 

buffer 1:【                                 】

buffer index offset length
0 0 7

插入 “文本”

buffer 0:【我们使用编辑器  】                 

buffer 1:【文本                                 】

buffer index offset length

0

0

4

1

0

2
0 4 3

删除 “我们”:

buffer 0:【我们使用编辑器  】                 

buffer 1:【文本                                 】

buffer index

offset

length

0

0

4

1

0

2

0

4

3

在 piece table 的实现中,两个buffer的内容都不会被删除。每次添加则是在buffer 1中增加一个piece.而每次删除仅仅是改变table的内容。这样的一个好处是我们只需要记住table的变化就可以实现undo和redo了。在每一个piece中加入一些其它的描述符,我们可以记录诸如字体等信息 。 很多文本编辑器都使用这种方法。

0
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics