Есть много способов сделать это.
Я бы посоветовал вам превратить дерево в отсортированный массив троек (parent, child, direction)
. Итак, начнем с tree1:
4
/ \
3 2
/ \ / \
5 8 10 22
Это быстро становится:
(None, 4, None) # top
(4, 3, L)
(3, 5, L)
(3, 8, L)
(4, 2, R)
(2, 10, L)
(2, 22, R)
Что вы сортируете, чтобы получить
(None, 4, None) # top
(2, 10, L)
(2, 22, R)
(3, 5, L)
(3, 8, L)
(4, 2, R)
(4, 3, L)
Сделайте то же самое с другими, а затем сравните их.
Учитывая дерево и разницу, вы можете сначала превратить дерево в эту форму, посмотреть на разницу, понять, в каком направлении это происходит, и получить желаемое представление с помощью патча. Затем вы можете рекурсивно восстановить другое дерево.
Причина, по которой я бы сделал это с этим представлением, состоит в том, что если два дерева имеют какие-либо общие поддеревья - даже если они расположены по-разному в главном дереве - они будут отображаться совместно. И поэтому вы, вероятно, получите сравнительно небольшие различия, если деревья действительно будут совпадать каким-то интересным образом.
Редактировать
Для точки из @ruakh предполагается, что значения не повторяются в дереве. Если они это сделают, то вы можете сделать такое представление:
4
/ \
3 2
/ \ / \
5 8 10 22
становится
(, 4)
(0, 3)
(00, 5)
(01, 8)
(1, 2)
(10, 10)
(11, 22)
А теперь, если вы переместите поддеревья, они будут отображаться как большие различия. Но если вы просто измените один узел, это все равно будет небольшая разница.