Day07_trees
Binary trees
Inductive bt (X : Type) : Type :=
| empty
| node (l : bt X) (v : X) (r : bt X).
Check empty.
Check @empty nat.
Check (node empty true empty). (* leaf node *)
Check (node empty 5 empty). (* leaf node *)
Check (node empty G (node empty C empty)).
Check (node (node empty 12 empty) 25 (node (node empty 5 empty) 5 empty)).
Compute (size (node (node empty 12 empty) 25 (node (node empty 5 empty) 5 empty))).
We defined some terminology already: a leaf is a node where both
children are empty.
The root of a tree is the topmost node.
Definition root {X : Type} (t : bt X) : option X :=
match t with
| empty ⇒ None
| node _ v _ ⇒ Some v
end.
Compute (root (node (node empty 12 empty) 25 (node (node empty 5 empty) 5 empty))).
(* ===> Some 25 *)
It's common enough to want to make a leaf that we'll define a
function to do it for us.
Definition leaf {X : Type} (v : X) : bt X := node empty v empty.
Compute (root (node (leaf 12) 25 (node (leaf 5) 5 empty))).
(* ===> Some 25 *)
Compute (root (node (leaf 12) 25 (node (leaf 5) 5 empty))).
(* ===> Some 25 *)
What are trees for?
- In interpreters, compilers, and program analyses to represent
and manipulate programs.
- In machine learning's so-called "decision trees".
- In game AI to represent strategies.
- In operating systems to store filesystem information.
- In databases to quickly manipulate stored values.
Inductive proper_noun : Type :=
| Prof_Greenberg
| Opie_the_dog
| Dr_Dave.
Inductive article : Type :=
| the
| a.
Inductive noun : Type :=
| program
| frisbee
| lasagna
| unicycle.
Inductive noun_phrase : Type :=
| np_proper (pn : proper_noun)
| np_compound (a : article) (n : noun).
Inductive verb_intransitive : Type :=
| laughed
| danced
| barked.
Inductive verb_transitive : Type :=
| bit
| wrote
| baked
| rode.
Inductive preposition : Type :=
| under
| around
| in_front_of.
Inductive adverb : Type :=
| goofily
| well
| sarcastically.
Inductive modifier : Type :=
| m_prep (p : preposition) (np : noun_phrase)
| m_adverb (a : adverb).
Inductive verb_phrase : Type :=
| vp_intransitive (v : verb_intransitive)
| vp_transitive (v : verb_transitive) (o : noun_phrase)
| vp_modifier (vp : verb_phrase) (m : modifier).
Inductive sentence : Type :=
| s (np : noun_phrase) (vp : verb_phrase).
Exercise: 1 star, standard (sentences)
Write a tree that models a sentence where Prof. Greenberg danced in front of Opie.
Write a tree that models a sentence where Opie bakes a lasagna
well. Good boy!
Translate the following tree to an English sentence.
Definition so_talented : sentence :=
s (np_proper Dr_Dave)
(vp_modifier
(vp_modifier
(vp_transitive rode (np_compound the unicycle))
(m_adverb goofily))
(m_prep around (np_compound the frisbee))).
(* FILL IN HERE *)
(* Do not modify the following line: *)
Definition manual_grade_for_sentences : option (nat×string) := None.
☐
s (np_proper Dr_Dave)
(vp_modifier
(vp_modifier
(vp_transitive rode (np_compound the unicycle))
(m_adverb goofily))
(m_prep around (np_compound the frisbee))).
(* FILL IN HERE *)
(* Do not modify the following line: *)
Definition manual_grade_for_sentences : option (nat×string) := None.
☐
Traversals
- A pre-order traversal puts the value first, then traverses the
left child, then the right child.
- An in-order traversal first traverses the left child, then the
value of the node, then the right child.
- A post-order traversal first traverses the left child, then the right child, then the value of the node.
Fixpoint inorder {X : Type} (t : bt X) : list X :=
match t with
| empty ⇒ []
| node l v r ⇒ inorder l ++ [v] ++ inorder r
end.
Compute (inorder (node (node empty 12 empty) 25 (node (node empty 5 empty) 5 empty))).
match t with
| empty ⇒ []
| node l v r ⇒ inorder l ++ [v] ++ inorder r
end.
Compute (inorder (node (node empty 12 empty) 25 (node (node empty 5 empty) 5 empty))).
Exercise: 2 stars, standard (traversals)
Define traversal functions preorder and postorder that implement those respective traversals.
(* FILL IN HERE *)
Write a tree that produces different output from all three
traversals. (Note the type!) It should have at least three
nodes.
Definition different_all_three : bt base (* REPLACE THIS LINE WITH ":= _your_definition_ ." *). Admitted.
Write a tree that produces the same output from pre- and in-order
traversals (but not post-order). It should have at least three
nodes.
Write a tree that produces the same output from in- and post-order
traversals (but not pre-order). It should have at least three
nodes.
Definition same_post_in : bt base (* REPLACE THIS LINE WITH ":= _your_definition_ ." *). Admitted.
(* Do not modify the following line: *)
Definition manual_grade_for_traversals : option (nat×string) := None.
☐
(* Do not modify the following line: *)
Definition manual_grade_for_traversals : option (nat×string) := None.
☐
Binary search trees (BSTs)
- t is empty, or
- t is node l v r where:
Exercise: 1 star, standard (search_property)
Write two trees of naturals that have the search property and two trees that do not. All of your trees should have at least two nodes.Definition bst1 : bt nat (* REPLACE THIS LINE WITH ":= _your_definition_ ." *). Admitted.
Definition bst2 : bt nat (* REPLACE THIS LINE WITH ":= _your_definition_ ." *). Admitted.
Definition non_bst1 : bt nat (* REPLACE THIS LINE WITH ":= _your_definition_ ." *). Admitted.
Definition non_bst2 : bt nat (* REPLACE THIS LINE WITH ":= _your_definition_ ." *). Admitted.
(* Do not modify the following line: *)
Definition manual_grade_for_search_property : option (nat×string) := None.
☐
Inductive ordering : Type :=
| LT
| EQ
| GT.
Fixpoint compare (n m : nat) : ordering :=
match n, m with
| O, O ⇒ EQ
| S _, O ⇒ GT
| O, S _ ⇒ LT
| S n', S m' ⇒ compare n' m'
end.
Compute (compare 0 0). (* ===> EQ *)
Compute (compare 0 10). (* ===> LT *)
Compute (compare 7 4). (* ===> GT *)
Compute (compare 1000 1000). (* ===> EQ *)
| LT
| EQ
| GT.
Fixpoint compare (n m : nat) : ordering :=
match n, m with
| O, O ⇒ EQ
| S _, O ⇒ GT
| O, S _ ⇒ LT
| S n', S m' ⇒ compare n' m'
end.
Compute (compare 0 0). (* ===> EQ *)
Compute (compare 0 10). (* ===> LT *)
Compute (compare 7 4). (* ===> GT *)
Compute (compare 1000 1000). (* ===> EQ *)
Here's a function that uses the search property to rapidly
determine whether or not a value is in a BST already.
Fixpoint lookup (n : nat) (t : bt nat) : bool :=
match t with
| empty ⇒ false
| node l v r ⇒
match compare n v with
| LT ⇒ lookup n l
| EQ ⇒ true
| GT ⇒ lookup n r
end
end.
match t with
| empty ⇒ false
| node l v r ⇒
match compare n v with
| LT ⇒ lookup n l
| EQ ⇒ true
| GT ⇒ lookup n r
end
end.
Exercise: 3 stars, standard (insert)
Write a function that inserts a number n into a binary search tree t. To get full credit, you should use the binary search property!
Fixpoint insert (n : nat) (t : bt nat) : bt nat (* REPLACE THIS LINE WITH ":= _your_definition_ ." *). Admitted.
☐
☐
Exercise: 2 stars, standard (remove_min)
Write a function that tries to remove the smallest element from a binary search tree. You'll need to return not just the smallest element, but also what's left of the tree.
Fixpoint remove_min (t : bt nat) : option (nat × bt nat) (* REPLACE THIS LINE WITH ":= _your_definition_ ." *). Admitted.
☐
☐
Exercise: 4 stars, standard (remove)
Write a function that removes a number n from a binary search tree. If n isn't in the tree, you should return the tree unchanged.- Handling empty should be simple.
- To remove n from node l v r, look at compare n v.
Fixpoint remove (n : nat) (t : bt nat) : bt nat (* REPLACE THIS LINE WITH ":= _your_definition_ ." *). Admitted.
☐
☐
Exercise: 4 stars, standard (is_bst)
Write a function is_bst that takes t : bt nat and returns true if t has the search property.- You'll need at least one helper function. How can you check the
"every value" parts of the search property?
- Don't think about efficiency---you're just making things hard for yourself. Get it to work first, and then make it efficient if that'll make you happy.
(* Do not modify the following line: *)
Definition manual_grade_for_is_bst : option (nat×string) := None.
☐
(* Mon Oct 12 08:48:48 PDT 2020 *)