(* Author: Tobias Nipkow *) (* Todo: minimal ipl of almost complete trees *)
section \<open>Binary Tree\<close>
theory Tree imports Main begin
datatype'a tree =
Leaf (\<open>\<langle>\<rangle>\<close>) |
Node "'a tree" ("value": 'a) "'a tree" (\(\indent=1 notation=\mixfix Node\\\_,/ _,/ _\)\)
datatype_compat tree
primrec left :: "'a tree \ 'a tree" where "left (Node l v r) = l" | "left Leaf = Leaf"
primrec right :: "'a tree \ 'a tree" where "right (Node l v r) = r" | "right Leaf = Leaf"
text\<open>Counting the number of leaves rather than nodes:\<close>
fun size1 :: "'a tree \ nat" where "size1 \\ = 1" | "size1 \l, x, r\ = size1 l + size1 r"
fun subtrees :: "'a tree \ 'a tree set" where "subtrees \\ = {\\}" | "subtrees (\l, a, r\) = {\l, a, r\} \ subtrees l \ subtrees r"
fun mirror :: "'a tree \ 'a tree" where "mirror \\ = Leaf" | "mirror \l,x,r\ = \mirror r, x, mirror l\"
class height = fixes height :: "'a \ nat"
instantiation tree :: (type)height begin
fun height_tree :: "'a tree => nat"where "height Leaf = 0" | "height (Node l a r) = max (height l) (height r) + 1"
instance ..
end
fun min_height :: "'a tree \ nat" where "min_height Leaf = 0" | "min_height (Node l _ r) = min (min_height l) (min_height r) + 1"
fun complete :: "'a tree \ bool" where "complete Leaf = True" | "complete (Node l x r) = (height l = height r \ complete l \ complete r)"
text\<open>Almost complete:\<close> definition acomplete :: "'a tree \ bool" where "acomplete t = (height t - min_height t \ 1)"
text\<open>Weight balanced:\<close> fun wbalanced :: "'a tree \ bool" where "wbalanced Leaf = True" | "wbalanced (Node l x r) = (abs(int(size l) - int(size r)) \ 1 \ wbalanced l \ wbalanced r)"
text\<open>Internal path length:\<close> fun ipl :: "'a tree \ nat" where "ipl Leaf = 0 " | "ipl (Node l _ r) = ipl l + size l + ipl r + size r"
fun preorder :: "'a tree \ 'a list" where "preorder \\ = []" | "preorder \l, x, r\ = x # preorder l @ preorder r"
fun inorder :: "'a tree \ 'a list" where "inorder \\ = []" | "inorder \l, x, r\ = inorder l @ [x] @ inorder r"
text\<open>A linear version avoiding append:\<close> fun inorder2 :: "'a tree \ 'a list \ 'a list" where "inorder2 \\ xs = xs" | "inorder2 \l, x, r\ xs = inorder2 l (x # inorder2 r xs)"
fun postorder :: "'a tree \ 'a list" where "postorder \\ = []" | "postorder \l, x, r\ = postorder l @ postorder r @ [x]"
text\<open>Binary Search Tree:\<close> fun bst_wrt :: "('a \ 'a \ bool) \ 'a tree \ bool" where "bst_wrt P \\ \ True" | "bst_wrt P \l, a, r\ \
(\<forall>x\<in>set_tree l. P x a) \<and> (\<forall>x\<in>set_tree r. P a x) \<and> bst_wrt P l \<and> bst_wrt P r"
abbreviation bst :: "('a::linorder) tree \ bool" where "bst \ bst_wrt (<)"
fun (in linorder) heap :: "'a tree \ bool" where "heap Leaf = True" | "heap (Node l m r) =
((\<forall>x \<in> set_tree l \<union> set_tree r. m \<le> x) \<and> heap l \<and> heap r)"
lemma neq_subtrees_empty[simp]: "subtrees t \ {}" by (cases t)(auto)
lemma neq_empty_subtrees[simp]: "{} \ subtrees t" by (cases t)(auto)
lemma size_subtrees: "s \ subtrees t \ size s \ size t" by(induction t)(auto)
lemma set_treeE: "a \ set_tree t \ \l r. \l, a, r\ \ subtrees t" by (induction t)(auto)
lemma Node_notin_subtrees_if[simp]: "a \ set_tree t \ Node l a r \ subtrees t" by (induction t) auto
lemma in_set_tree_if: "\l, a, r\ \ subtrees t \ a \ set_tree t" by (metis Node_notin_subtrees_if)
subsection \<open>\<^const>\<open>height\<close> and \<^const>\<open>min_height\<close>\<close>
lemma eq_height_0[simp]: "height t = 0 \ t = Leaf" by(cases t) auto
lemma eq_0_height[simp]: "0 = height t \ t = Leaf" by(cases t) auto
lemma height_map_tree[simp]: "height (map_tree f t) = height t" by (induction t) auto
lemma height_le_size_tree: "height t \ size (t::'a tree)" by (induction t) auto
lemma size1_height: "size1 t \ 2 ^ height (t::'a tree)" proof(induction t) case (Node l a r) show ?case proof (cases "height l \ height r") case True have"size1(Node l a r) = size1 l + size1 r"by simp alsohave"\ \ 2 ^ height l + 2 ^ height r" using Node.IH by arith alsohave"\ \ 2 ^ height r + 2 ^ height r" using True by simp alsohave"\ = 2 ^ height (Node l a r)" using True by (auto simp: max_def mult_2) finallyshow ?thesis . next case False have"size1(Node l a r) = size1 l + size1 r"by simp alsohave"\ \ 2 ^ height l + 2 ^ height r" using Node.IH by arith alsohave"\ \ 2 ^ height l + 2 ^ height l" using False by simp finallyshow ?thesis using False by (auto simp: max_def mult_2) qed qed simp
corollary size_height: "size t \ 2 ^ height (t::'a tree) - 1" using size1_height[of t, unfolded size1_size] by(arith)
lemma height_subtrees: "s \ subtrees t \ height s \ height t" by (induction t) auto
lemma min_height_le_height: "min_height t \ height t" by(induction t) auto
lemma min_height_map_tree[simp]: "min_height (map_tree f t) = min_height t" by (induction t) auto
lemma min_height_size1: "2 ^ min_height t \ size1 t" proof(induction t) case (Node l a r) have"(2::nat) ^ min_height (Node l a r) \ 2 ^ min_height l + 2 ^ min_height r" by (simp add: min_def) alsohave"\ \ size1(Node l a r)" using Node.IH by simp finallyshow ?case . qed simp
lemma complete_iff_height: "complete t \ (min_height t = height t)" apply(induction t) apply simp apply (simp add: min_def max_def) by (metis le_antisym le_trans min_height_le_height)
lemma size1_if_complete: "complete t \ size1 t = 2 ^ height t" by (induction t) auto
lemma size_if_complete: "complete t \ size t = 2 ^ height t - 1" using size1_if_complete[simplified size1_size] by fastforce
lemma size1_height_if_incomplete: "\ complete t \ size1 t < 2 ^ height t" proof(induction t) case Leaf thus ?caseby simp next case (Node l x r) have 1: ?caseif h: "height l < height r" using h size1_height[of l] size1_height[of r] power_strict_increasing[OF h, of "2::nat"] by(auto simp: max_def simp del: power_strict_increasing_iff) have 2: ?caseif h: "height l > height r" using h size1_height[of l] size1_height[of r] power_strict_increasing[OF h, of "2::nat"] by(auto simp: max_def simp del: power_strict_increasing_iff) have 3: ?caseif h: "height l = height r"and c: "\ complete l" using h size1_height[of r] Node.IH(1)[OF c] by(simp) have 4: ?caseif h: "height l = height r"and c: "\ complete r" using h size1_height[of l] Node.IH(2)[OF c] by(simp) from 1 2 3 4 Node.prems show ?caseapply (simp add: max_def) by linarith qed
lemma complete_iff_min_height: "complete t \ (height t = min_height t)" by(auto simp add: complete_iff_height)
lemma min_height_size1_if_incomplete: "\ complete t \ 2 ^ min_height t < size1 t" proof(induction t) case Leaf thus ?caseby simp next case (Node l x r) have 1: ?caseif h: "min_height l < min_height r" using h min_height_size1[of l] min_height_size1[of r] power_strict_increasing[OF h, of "2::nat"] by(auto simp: max_def simp del: power_strict_increasing_iff) have 2: ?caseif h: "min_height l > min_height r" using h min_height_size1[of l] min_height_size1[of r] power_strict_increasing[OF h, of "2::nat"] by(auto simp: max_def simp del: power_strict_increasing_iff) have 3: ?caseif h: "min_height l = min_height r"and c: "\ complete l" using h min_height_size1[of r] Node.IH(1)[OF c] by(simp add: complete_iff_min_height) have 4: ?caseif h: "min_height l = min_height r"and c: "\ complete r" using h min_height_size1[of l] Node.IH(2)[OF c] by(simp add: complete_iff_min_height) from 1 2 3 4 Node.prems show ?case by (fastforce simp: complete_iff_min_height[THEN iffD1]) qed
lemma complete_if_size1_height: "size1 t = 2 ^ height t \ complete t" using size1_height_if_incomplete by fastforce
lemma complete_if_size1_min_height: "size1 t = 2 ^ min_height t \ complete t" using min_height_size1_if_incomplete by fastforce
lemma complete_iff_size1: "complete t \ size1 t = 2 ^ height t" using complete_if_size1_height size1_if_complete by blast
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.