一、背景:
2022年10月左右业务需求需要实现两个数据表格对比,能够比对当前版本和任意版本的对比,当时公司环境服务端大哥已提离职,不太愿意接。鉴于客户电脑配置不错,遂借助webworker的力量实现前端diff。
二、目标:
实现数据表格的比对,其中包括几种状态:
-
- 行级:
-
-
- 新增行
- 删除行
- 忽略行(通过特殊指令标记当前行无需进行比对)
- 未修改行
-
-
- 单元格级:
-
-
- 已被修改的单元格
- 已被忽略的单元格
-
除此之外还需要实现两个表格之间相同的行之间有箭头指引(方便观看)
三、调研:
经同事指点,调研了Myers Diff算法,但涉及到二叉树以及动态规划原理不是很拿手,经过思考后尝试使用双指针方法实现。
四、实现思路:
设oldStr为当前版本(蓝本), newStr为被比对版本。
oldStr = ABCDACB, newStr = CACBCAB
// step0:设置双指针
↓(主指针: master)
A B C D A C B // old
C A C B C A B // new
↑(次指针: visitor)
// 当前master !== visitor,所以当前visitor记为新增,并且visitor指针向后进一。
// 此时情况:
↓ // master
A B C D A C B // old
C A C B C A B // new
+ ↑ // visitor
↓ // master
A B C D A C B // old
C A C B C A B // new
+ ↑ // visitor
↓ // master
A B C D A C B // old
C A C B C A B // new
+ + ↑ // visitor
↓ // master
A B C D A C B // old
C A C B C A B // new
+ + ↑ // visitor
↓ // master
A B C D A C B // old
C A C B C A B // new
+ + ↑ // visitor
因为D不等于A,所以visitor向下寻找
↓ // master
A B C D A C B // old
C A C B C A B // new
+ + ↑ // visitor
D不等于B,所以继续寻找,但当前队列已经找完,所以标记D为被删除元素。master指针进一,visitor指针返回原位
- ↓ // master
A B C D A C B // old
C A C B C A B // new
+ + ↑ // visitor
- ↓ // master
A B C D A C B // old
C A C B C A B // new
+ + ↑ // visitor
master对应的C未找到对应,同上
- - ↓ // master
A B C D A C B // old
C A C B C A B // new
+ + ↑ // visitor
C A C B C D A C B + + - -
五、时间复杂度分析:
N = oldStr.length, M = newStr.length
situation | 时间复杂度 | 释义 |
最好情况 | O(M > N ? N : M) | master为visitor的子级(master中每个元素都没有被删除),此时完成master的diff则完成输出,visitor剩余部分全部为新增。 |
最坏情况 | O(M * N) | master中每个当前字符都无法在visitor中找到对应。 |