【发布时间】:2011-05-11 03:00:47
【问题描述】:
这是一道面试题。您将使用什么数据结构将文本存储在文本编辑器中?
【问题讨论】:
标签: data-structures text-editor
这是一道面试题。您将使用什么数据结构将文本存储在文本编辑器中?
【问题讨论】:
标签: data-structures text-editor
正如@Vovanium 已经提到如何使用间隙缓冲区的基本理论,我已经实现了一个 C/C++ 版本。
代码:
#include <stdio.h>
#define SZ 1000
char leftArray[SZ], rightArray[SZ];
int leftCount, rightCount;
int cursorPos;
/*
* Private APIs
*/
void printArray(){
for(register int i = 0; i < leftCount; i++){
printf("%c", leftArray[i]);
}
for(register int i = rightCount - 1; i >= 0; i--){
printf("%c", rightArray[i]);
}
printf("\n");
}
void adjust(int pos){
while(leftCount > pos){
rightArray[rightCount++] = leftArray[--leftCount];
}
while(leftCount < pos){
leftArray[leftCount++] = rightArray[--rightCount];
}
}
/*
* Public APIs for Text Editor
*/
void init(){
cursorPos = leftCount = rightCount = 0;
}
void addWord(char word[], int len){
adjust(cursorPos);
for(register int i = 0; i < len; i++){
leftArray[leftCount++] = word[i];
}
leftArray[leftCount] = 0;
}
void addBackSpace(){
adjust(cursorPos);
leftCount--;
}
void moveCurson(int newPosition){
cursorPos = newPosition;
}
void subString(int pos, int length, char result[]){
adjust(cursorPos);
int k = 0;
int l = 0;
while(k + pos < leftCount && k < length){
result[k] = leftArray[pos + k];
k++;
}
length -= k;
while( l < length){
result[k++] = rightArray[rightCount - 1 - l];
l++;
}
}
【讨论】:
我知道现在回答为时已晚,但我发现 The Craft of Text Editing 这本书真的很有用。它包含对几种缓冲模型及其优缺点的描述。不幸的是,它没有提到 Ropes 数据结构。
【讨论】:
在旧的 ZX-Spectrum 上,一个(或多个,我不知道)文本编辑器使用非常简单的结构。
有一个大缓冲区,占用了所有空闲 RAM。文本在光标处分成两部分。光标之前的部分放在缓冲区的开头,其余部分放在缓冲区的末尾。输入文本时,只需将数据添加到第一部分的末尾,当光标移动时,文本会前后复制。
缓冲区布局:
Hello, World!
^------Cursor here
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|H|e|l|l|o|,| |W| <free> |o|r|l|d|!|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ^ ^ |
begin cur1 cur2 end
也就是说,一些编辑操作是如何进行的:
Type a char: buffer[cur1++] = character
Backspace: cur1--
Cursor left: buffer[--cur2] = buffer[--cur1]
Cursor right: buffer[cur1++] = buffer[cur2++]
缓冲作用:
Hello, W..............orld!
Press right ^ ^
Hello, Wo..............rld!
Press backspace ^ ^
Hello, W...............rld!
Press 0 ^ ^
Hello, W0..............rld!
^ ^
【讨论】:
绳子本质上是一棵二叉树,其叶子是字符数组。树中的一个节点有一个左孩子和一个右孩子——左孩子是字符串的第一部分,而右孩子是字符串的最后部分。两条绳索的连接只涉及创建一个以两条绳索作为子节点的新树节点。为了确保对数时间索引和子串操作,可能需要平衡生成的绳索。各种平衡策略都是可能的。
与将字符串存储为字符数组相比,ropes 的主要优点是它们可以比普通字符串更快地连接,并且不需要大的连续内存空间来存储大字符串。主要缺点是更大的整体空间使用和更慢的索引,随着树结构变得更大和更深,这两者都变得更加严重。然而,索引的许多实际应用只涉及对字符串的迭代,只要叶节点足够大以受益于缓存效应,它就会保持快速。
【讨论】:
【讨论】: