【问题标题】:Data structure for text editor文本编辑器的数据结构
【发布时间】:2011-05-11 03:00:47
【问题描述】:

这是一道面试题。您将使用什么数据结构将文本存储在文本编辑器中?

【问题讨论】:

标签: data-structures text-editor


【解决方案1】:

正如@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++;
    }
}

【讨论】:

    【解决方案2】:

    我知道现在回答为时已晚,但我发现 The Craft of Text Editing 这本书真的很有用。它包含对几种缓冲模型及其优缺点的描述。不幸的是,它没有提到 Ropes 数据结构。

    【讨论】:

      【解决方案3】:

      在旧的 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!
                            ^             ^
      

      【讨论】:

      • 供参考:这称为“gab 缓冲区”。大多数实现在您移动光标时不会移动缓冲区。他们只是在插入/删除操作中执行此操作。
      • @Aaron Digulla:谢谢,很好的补充。两种实现都有其原因。
      • 这里有一个错字:它叫做 gap buffer 这里是more information from Wikipedia
      • 如何管理多行?每行有一个间隙缓冲区还是整个文档只有一个? AFAIK 在单个间隙缓冲区的情况下,这意味着移动光标的大量数据从开始移动到结束。或者在这样的编辑器中不允许跨行移动光标? (仅左/右)
      【解决方案4】:

      Rope

      绳子本质上是一棵二叉树,其叶子是字符数组。树中的一个节点有一个左孩子和一个右孩子——左孩子是字符串的第一部分,而右孩子是字符串的最后部分。两条绳索的连接只涉及创建一个以两条绳索作为子节点的新树节点。为了确保对数时间索引和子串操作,可能需要平衡生成的绳索。各种平衡策略都是可能的。

      与将字符串存储为字符数组相比,ropes 的主要优点是它们可以比普通字符串更快地连接,并且不需要大的连续内存空间来存储大字符串。主要缺点是更大的整体空间使用和更慢的索引,随着树结构变得更大和更深,这两者都变得更加严重。然而,索引的许多实际应用只涉及对字符串的迭代,只要叶节点足够大以受益于缓存效应,它就会保持快速。

      【讨论】:

      • +1 告诉我我重新发明的结构(原文如此),在我的一篇帖子中描述和建议的正式名称是什么 :-)
      • @thkala:先做一些研究是值得的——太阳底下没有新鲜事;-)
      • 除了连接之外,对于许多删除、插入和替换操作,绳索通常相对较好(与完全连续的存储相比),尤其是在文档开头附近或增长连续存储需要在记忆中移动。
      • @Tony:几年前我在课堂上学到了大约半吨数据结构,但英语不是我的母语,教授们在提供英语术语方面并不一致。我的英语很好,但有时很难将您记得的内容与其普遍接受的名称相匹配......“这是一棵具有这个和那个特征的树”并不总是有帮助:-/
      • 顺便说一句,我刚刚更新了二叉树上的维基百科页面以包含指向绳索数据结构的链接......几天前会非常有帮助:-)
      【解决方案5】:

      您可能会觉得这很有趣,即使它不能完全回答您的问题:

      Most efficient data structure to add styles to text

      我希望讨论会去有趣的地方:-)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多