git diff的生成方式:myers diff算法

概述

本文参考:https://blog.jcoglan.com/2017/02/12/the-myers-diff-algorithm-part-1/

每个开发者多少都接触过git的diff功能,如下图:
在这里插入图片描述

该功能能够展示出某个文件的改动信息,非常便于开发者的日常开发。
本文将探讨下此功能实现的原理。

myers diff 做了啥

引用个例子

a = ABCABBA
b = CBABAC

现在要找出ab之间的diff。仔细想一想,我们会发现其实两者之间的diff情况是有无数个的,比如可以找到以下几种情况:

1.  - A       2.  - A       3.  + C
    - B           + C           - A
      C             B             B
    - A           - C           - C
      B             A             A
    + A             B             B
      B           - B           - B
      A             A             A
    + C           + C           + C

但是实际我们使用的时候,期望的看到的是最优的一种情况,最好是满足以下两个标准的:

  1. diff的内容最少
  2. 删除的内容在增加的内容之前

根据这两个标准,这个例子中我们可以得到最优解,如下:

- A
- B
  C
+ B
  A
  B
- B
  A
+ C

myers diff 思路

myers diff算法中,将 寻找 diff 的过程表示为了图搜索,如下图:

       A     B     C     A     B     B     A

    o-----o-----o-----o-----o-----o-----o-----o   0
    |     |     | \   |     |     |     |     |
C   |     |     |  \  |     |     |     |     |
    |     |     |   \ |     |     |     |     |
    o-----o-----o-----o-----o-----o-----o-----o   1
    |     | \   |     |     | \   | \   |     |
B   |     |  \  |     |     |  \  |  \  |     |
    |     |   \ |     |     |   \ |   \ |     |
    o-----o-----o-----o-----o-----o-----o-----o   2
    | \   |     |     | \   |     |     | \   |
A   |  \  |     |     |  \  |     |     |  \  |
    |   \ |     |     |   \ |     |     |   \ |
    o-----o-----o-----o-----o-----o-----o-----o   3
    |     | \   |     |     | \   | \   |     |
B   |     |  \  |     |     |  \  |  \  |     |
    |     |   \ |     |     |   \ |   \ |     |
    o-----o-----o-----o-----o-----o-----o-----o   4
    | \   |     |     | \   |     |     | \   |
A   |  \  |     |     |  \  |     |     |  \  |
    |   \ |     |     |   \ |     |     |   \ |
    o-----o-----o-----o-----o-----o-----o-----o   5
    |     |     | \   |     |     |     |     |
C   |     |     |  \  |     |     |     |     |
    |     |     |   \ |     |     |     |     |
    o-----o-----o-----o-----o-----o-----o-----o   6

    0     1     2     3     4     5     6     7

找到图中从左上到右下的最短路径就是找到了最优的diff。
右表示“删除”,向下表示”新增“,对角线则表示“原内容保持不动“。

寻找路径需要满足两个特点:

  1. 路径长度最短(对角线不算长度)
  2. 先向右,再向下(先删除,后新增)

动态规划

如此,要找到第n步的最短路径,那么就需要找到第n-1步的最短路径,以此类推,就需要从第2步,第1步开始就走最优解。

就拿(2,2)这个点举例,可以到达它的路径有以下:
(0,0)->(1,0)->(2,2)
(0,0)->(1,0)->(1,1)->(1,2)->(2,2)
(0,0)->(1,0)->(1,1)->(2,1)->(2,2)
(0,0)->(1,0)->(2,0)->(2,1)->(2,2)
(0,0)->(0,1)->(2,2)
(0,0)->(0,1)->(1,1)->(1,2)->(2,2)
(0,0)->(0,1)->(1,1)->(2,1)->(2,2)
(0,0)->(0,1)->(0,2)->(1,2)->(2,2)
由于要遵循先右后下的原则,因此到达(2,2)最优的方案就是
(0,0)->(1,0)->(2,2)

倘若从(0,0)开始走,每条路径仅保留最优解的话,最终可以得到有以下路径:

0,0 --- 1,0 --- 3,1 --- 5,2 --- 7,3
 |       |       |
 |       |       |
0,1     2,2     5,4 --- 7,5
 |               |       |
 |               |       |
2,4 --- 4,5     5,5     7,6
 |       |       |
 |       |       |
3,6     4,6     5,6

myers diff 概念

myers diff 中引入了k和d 两个概念来方便计算最短路径。

k: k=x-y,x与y分别是横竖方向上的位置
d: 走的步数 ,走斜线不算步数

根据这两个参数可以得到下图:
在这里插入图片描述

在d相同的情况下,k越小,越接近终点。
因此最优解也就可以筛选出来了。

©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页