Я бы начал с индуктивного определения непустого двоичного дерева.
Inductive nonemptyTree :=
| Endpoint
| Single (l : nonemptyTree)
| Double (l : nonemptyTree) (r : nonemptyTree).
Это выглядит немного сложнее, чем обычное двоичное дерево, но с четким разграничением различных образований и удалением типичного конструктора "Nil", помогающего в доказательстве.
Оттуда вы захотите определить, что такое «ссылки» и «узлы» и как их вычислять по дереву. Это довольно легко, учитывая определение nonemptyTree
.
Fixpoint links (t : nonemptyTree) : nat :=
match t with
| Endpoint => 0
| Single l => 1 + links l
| Double l r => 2 + links l + links r
end.
Fixpoint nodes (t : nonemptyTree ) : nat :=
match t with
| Endpoint => 1
| Single l => 1 + nodes l
| Double l r => 1 + nodes l + nodes r
end.
В этот момент нам просто нужно доказать, что для всех деревьев t
, nodes t = links t + 1
. Осталось рассмотреть только три случая, и вы уже получили первый (базовый вариант).