GapBuffer高效标记管理算法

news/2025/10/19 15:28:50/文章来源:https://www.cnblogs.com/RainbowC0/p/18805061

目录
  • 引言
  • GapBuffer 基本思想
    • 基本操作
  • 基于下标映射的标记记录法
    • 下标映射
    • 搜索
    • 维护
    • 对比
  • 总结

引言

最近笔者正在优化 Android 开源代码编辑器项目 TextWarrior 的一些算法,包括时间、空间两方面。TextWarroir 的文本编辑器算法采用经典的 GapBuffer,其基本思想是利用编辑时的局部性原理,在光标处维护一个缓冲区,实现高效替换。

但是笔者需要对其代码高亮、自动断行等功能用到的标记数组进行优化:

  • 原编辑器的代码高亮标记数组直接采用差分数组存储其文本下标,好处是文章内容频繁更新时差分数组可以只需要改动其中一两个元素的值便能导致后面整体的改动,缺点是查找某个下标时需要从头开始,时间复杂度为 \(O(N)\)
  • 原编辑器的自动断行标记数组直接存储文本下标,好处是定位时可以采用二分查找,但是当文本改动时需要对整个数组光标处的后半段进行修改,时间复杂度 \(O(N)\)

不管是差分数组还是直接存下标,貌似都有其缺陷。那有没有一种两全其美的方法呢?答案是有的。这要从 GapBuffer 说起。

GapBuffer 基本思想

GapBuffer 又叫间隙缓冲区,是一种文本编辑器算法,主要对编辑器中频繁的字符串插入、删除操作进行优化。

我们知道,对于中间插入,数组的时间复杂度为 \(O(N)\),而链表的时间复杂度为 \(O(1)\)。字符串常常用数组的方式存储,若采用链表,每个字符都会附带一个指针指向下一个字符结点,数据冗余度很高。而 GapBuffer 则实现了对于数组高效的中间插入删除。

GapBuffer 利用编辑时的局部性——编辑操作在一段时间内往往集中在最初光标附近,换位置的情况比较少这一事实——进行优化。GapBuffer 在原字符串数组光标附近维护一个缓冲区(即所谓间隙缓冲区,后文简称间隙),并通过双指针限定该间隙的范围。

由于间隙内的内容实际不可见,当我通过字符串索引获取字符时,需要跳过间隙,此时存在一个下标映射:将获取字符时的逻辑下标映射到所维护字符数组的实际下标。

基本操作

  • 局部性编辑:当光标位于间隙开始位置时,输入时直接将输入内容从间隙开始位置拷贝到间隙,并后移起始指针;删除时,直接前移起始指针。此时时间复杂度为 \(O(1)\)

  • 跨域编辑:若出现跨域编辑,即此时光标位置不在间隙开始处,则需要进行整体复制,以将间隙移动到当前光标处,再进行相关操作。时间复杂度 \(O(m)\),其中 \(m\) 表示间隙区移动的距离。

  • 若插入时间隙所剩空间不足,则需要进行扩容,并把间隙后的字符全部向后整体复制。时间复杂度 \(O(k)\),其中 \(k\) 为间隙之后的部分数组长度。

插入操作示例:

插入前
|H|e|l|l|o| | | | |W|o|r|l|d|^ Gap (size=4)
插入后
|H|e|l|l|o|!| | | |W|o|r|l|d|^ Gap (size=3)

删除操作示例:

删除前
|H|e|l|l|o|!| | | |W|o|r|l|d|^ Gap (size=3)
插入后
|H|e|l|l|o|!| | | |W|o|r|l|d|^ Gap (size=4)

基于下标映射的标记记录法

既然 GapBuffer 采用下标映射实现实际下标和逻辑下标的转换,而在编辑的过程中,某个字符的逻辑下标往往是不断变动的,而其实际下标则要稳定得多,因此完全可以记录实际下标实现高效率的标记管理。

记录实际下标,即记录标记在原字符数组中的下标,当间隙发生变动时维护下标的映射关系。可以对比逻辑下标和差分下标,实际下标+映射方式兼具二者有点同时避免了各自的缺陷。

下标映射

在需要访问下标时,会用到 GapBuffer 的下标映射函数将记录的实际下标转为逻辑下标再返回,而增加记录时会把逻辑下标转为实际下标进行记录。

private ArrayList<Integer> records;private int mapToReal(int i) {return i < gapStart ? i : i + gapLength();
}private int mapToLogical(int i) {return i < gapEnd ? i : i - gapLength();
}public void getMark(int i) {return mapToLogical(records.get(i));
}public void addMark(int i) {records.add(mapToReal(i));
}

搜索

在需要进行查找时,只需要将逻辑下标转为实际下标并应用二分查找即可,时间复杂度 \(O(\log N)\),继承了记录逻辑下标的优点,而记录差分下标则必须从头遍历累加。

public int findMark(int i) {return Collections.binarySearch(records, mapToReal(i));
}

维护

由于记录为实际下标,因此维护需保证与 GapBuffer 的一致性。对于间隙维护的三种情况均需考虑,其时间复杂度也和三种情况基本对等:

  • 局部性编辑:在间隙开头插入时,如果间隙不需要扩容,则记录不变,如果是删除,检查并处理实际下标落入间隙区中的下标,移动或删除,平均时间复杂度 \(O(1)\)。由于间隙发生了改变,虽然实际下标没有改变,但映射函数的参数发生变化,因此映射到的逻辑下标会变化。

  • 跨域编辑:在间隙以外的地方插入或删除,此时只需检查移动区间内的下标并加或减去间隙长度,再同上处理插入删除情况,时间复杂度 \(O(m)\),此处 \(m\) 为移动区间内标记数量。

  • 间隙扩容:当间隙大小不足插入时需要进行扩容,此时需要将间隙之后的所有标记加上扩容量,时间复杂度 \(O(k)\),此处 \(k\) 为间隙之后的标记数量。

实际下标记录的维护在满足局部性的情况下时间复杂度为 \(O(1)\),与差分下标记录同级,同时避免了逻辑辑下标记录的不足。当然,实际下标记录的维护难度要比二者大一些。

对比

下标记录方法 逻辑下标 差分下标 实际下标
访问 直接读取O(1) 前缀和O(n) 线性映射O(1)
搜索 二分O(logN) 线性O(n) 二分O(logN)
维护 O(k) O(1) O(1),最坏O(k)

总结

本文讨论文本编辑器经典算法 GapBuffer 的标记记录优化方案,利用算法中的局部性思想提出配套的基于映射的下标记录算法,并对比了 TextWarrior 用到的两种记录方案,表现出该方法在时间复杂度上的优势。另外,局部性原理也是很多算法的依据,在计算机软硬件设计很多地方都有所体现,值得研究。希望本文为读者提供一些参考帮助。


原文链接:https://www.cnblogs.com/RainbowC0/p/18805061 ,未经作者许可禁止转载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/940370.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2025年变位机厂家推荐排行榜,焊接变位机,双轴变位机,高精度智能变位机公司推荐!

2025年变位机厂家推荐排行榜,焊接变位机,双轴变位机,高精度智能变位机公司推荐!随着工业自动化和智能制造的快速发展,变位机、焊接变位机和双轴变位机在制造业中的应用越来越广泛。这些设备不仅能够提高生产效率,…

stable-virtio

https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/

2025年中医师承与确有专长培训机构推荐榜单:权威认证,传承经典,专业师资助力中医梦想!

2025年中医师承与确有专长培训机构推荐榜单:权威认证,传承经典,专业师资助力中医梦想!随着中医药事业的蓬勃发展,越来越多的人开始关注并投身于中医的学习和实践。中医师承与确有专长培训作为培养中医人才的重要途…

从数学概念到图像识别,再到 CNN 的联系

在矩阵论和信号处理中,奇异值分解(Singular Value Decomposition, SVD) 是一个极其重要的工具。它不仅是一个数学分解公式,更是连接数据压缩、特征提取和深度学习优化的桥梁 。 矩阵与奇异值的定义对任意矩阵 \(A …

2025流量计厂家推荐弗罗迈测控,高精度耐腐蚀多种类选择!

2025流量计厂家推荐弗罗迈测控,高精度耐腐蚀多种类选择!随着工业自动化和智能化的快速发展,流量计作为关键的测量设备,在各个行业中扮演着越来越重要的角色。特别是在2025年,随着技术的不断进步和市场需求的多样化…

关于代码规范的自我约束

关于代码规范的自我约束1.变量名不用拼音或单个字母,比如不用 “shuzu”“a”,改用 “studentList”“count”,让人一看就知道啥意思。 2.写代码前先空两格缩进,同一层的代码对齐,像排队一样整齐,嵌套多了也不乱…

7.switch语句的简单应用

swtich分支语法 switch分支结构用于在多个可能的情况下选择一种情况进行处理。以下是switch分支结构的基本语法: 另一种排版习惯: 当变量表达式所表达的量与其中一个case分支中的常量相符时,就执行此case分支后面的…

在AI技术唾手可得的时代,挖掘电池管理工具的新需求成为关键

本文分析了一款针对Apple Silicon Mac设备的电池充电限制工具,探讨其核心功能、应用场景及用户使用方式,并基于大量用户反馈总结出潜在的功能需求,为产品迭代提供方向。a.内容描述核心功能定位:该工具专为Apple Si…

计算语言学家在科技行业的职业发展指南

本文由某中心高级应用科学家分享计算语言学家在科技行业的职业发展建议,涵盖实习机会、研究方向选择、学术与产业研究差异以及非计算背景语言学家的就业路径等实用指导。计算语言学家能在科技行业找到归属吗? 某中心…

新奇特:神经网络的集团作战思维,权重共享层的智慧 - 指南

新奇特:神经网络的集团作战思维,权重共享层的智慧 - 指南pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consol…

2025防水篷布优质厂家推荐:成硕达塑业多功能产品覆盖多领域!

2025防水篷布优质厂家推荐:成硕达塑业多功能产品覆盖多领域!随着科技的不断进步和市场需求的多样化,多功能防水篷布在各个领域的应用越来越广泛。从聚乙烯帐篷到汽车篷布,从宴会用篷布到农林用盖草布,再到泳池布和…

读《数学之美》有感

读《数学之美》有感之前听算法郑老师推荐《数学之美》时,还以为会是本满是公式的难读书,实际翻开才发现完全不一样。 书里没讲复杂的推导,反而从我们每天用的搜索引擎、语音识别说起,把这些功能背后的数学逻辑拆解…

近期应急响应靶场总结

近期应急响应靶场总结 1、黑客webshell里面的flag 一般来说webshell里面的木马有php相关的eval执行代码我们可以以这个为契机,直接进行搜索,不同语言的执行函数不大一样 find ./ type f -name "*.jsp" | x…

Atcoder Beginner Contest 428 补题记录 - Inversentropir

C. Brackets Stack Query 题目大意 给予你 1 个空的字符串与 \(q\) 个询问,形如 1 ( 的询问将在字符串后增加 1 个 ( 字符,形如 2 的询问将会移除最后 1 个字符。在每次询问之后,你需要回答当前字符串中的左右括号是…

【URP】Unity中Mipmap是如何实现的?

《Unity URP中的MipMap技术解析》摘要:本文详解Unity URP管线中的MipMap多级渐远纹理技术,通过预生成分辨率递减的纹理金字塔(如256256→128128→...→11),根据物体距离动态选择纹理层级。重点阐述:1)硬件自动生…

2025彩钢制品优质厂家推荐:腾越彩钢,一站式钢结构解决方案!

2025彩钢制品优质厂家推荐:腾越彩钢,一站式钢结构解决方案!随着建筑行业的不断发展,彩钢瓦、镀锌板、折弯件、C型钢、Z型钢、压型瓦、楼承板、钢结构安装及次檩条等产品在各类工程项目中的应用越来越广泛。然而,这…

SQL中BOM递归查询语句

向下递归查询 WITH CTE AS ( -- 锚点:LT-W-00000001 SELECT bom_no,prd_no,zc_no,id_no,0 AS Level -- 层级:0 表示起始 FROM tf_bom WHERE bom_no = LT-W-00000001-> UNION ALL -- 递归:查找下…

ICCV 2025 (Highlight) Being-VL:师夷长技,用NLP的BPE算法统一视觉语言模型 - 实践

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

详细介绍:JVM 性能诊断

详细介绍:JVM 性能诊断2025-10-19 14:58 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; fon…

wqs 二分(凸完全单调性)

大学习 https://www.cnblogs.com/FloatingLife/p/19093641。 前置:斜率优化。我写的凸完全单调性(wqs 二分),有两个要素:凸,完全单调。 (施工中)以下是博客签名,正文无关 本文来自博客园,作者:Wy_x,转载请…