Comparing two roots tells you something changed; comparing subtree hashes tells you where. Today you diff two trees by walking down only where hashes differ.
Find which leaf changed by walking the two trees down where subtree hashes differ.
If two trees have the same root, they hold identical data - no need to look further. If the roots differ, the change is somewhere below, and the subtree hashes tell you where: descend into a child only when its hash differs between the two trees. Any subtree whose hash matches is provably identical and gets skipped whole. Follow the mismatches down to level 0 and you arrive at exactly the leaves that changed.
This is the git/rsync trick for syncing data cheaply. Rather than compare every
item, you compare O(log n) hashes per changed leaf and prune entire unchanged
branches at the top. Here, changing carol to trent makes the root differ, then the
right subtree differ, then leaf 2 differ - and the walk reports [2]. Two identical
trees short-circuit at the root and report nothing.
func Diff(a, b *Tree) []int {var out []intvar walk func(level, idx int)walk = func(level, idx int) {if a.Levels[level][idx] == b.Levels[level][idx] { return } // subtree equal, pruneif level == 0 { out = append(out, idx); return }walk(level-1, 2*idx)walk(level-1, 2*idx+1)}walk(len(a.Levels)-1, 0)return out}