List abbreviations

Our BSL provides us with an abbreviation (shorthand) to create lists. The abbreviation is a function called list and we can use it to create non-empty lists. You should still use empty for the empty list.

> (list 1 2)
(cons 1 (cons 2 '()))

More recursive data definitions; Trees

Lists are one of many data definitions that are recursive. Another popular data definition that uses recursion is a Binary Tree.

A binary tree is either an empty node that we call a leaf or a node (or non-leaf) that contains

  1. a value; we will use Number for our example

  2. a left child or left sub-tree

  3. a right chilkd or right sub-tree

Here are some examples.

A leaf node is a BT
Figure 1. A leaf node is a BT
A single non-leaf node
Figure 2. A single non-leaf node
A multiple nodes, balanced tree.
Figure 3. A multiple nodes, balanced tree.
Multiple nodes unbalanced tree
Figure 4. Multiple nodes unbalanced tree

Here is a data definition for a BT

;;;; Data Definition:

(define-struct leaf ())    (1)
(define-struct node (value left right))

;; A BinaryTree (BT) is one of
;; - (make-leaf)
;;   INTERP: represents an empty leaf node
;; - (make-node Number BT BT)             (2)
;;   INTERP: represents a node with a value and 2 children
;;
;;INTERP: represents a binary tree
1 A leaf is a struct that contains no slots
2 A node is a struct that contains the value and two slots that both have a BT.

Let’s write down our deconstructor template

;; Deconstructor Template:
;; bt-fn: BT -> ???
#; (define (bt-fn bt)
     (cond
       [(leaf? bt) ...] (1)
       [(node? bt) ... (node-val bt) ...  (2)
                   ... (bt-fn (node-left bt)) ... (3)
                   ... (bt-fn (node-right bt)) ...])) (4)
1 when we are given a leaf, eventhough it is a structure, the structure has not slots and thus nothing more to deconstruct here
2 when we are given a node however we have the node’s value which is a scalar
3 the node’s left sub-tree which is a BT again. So we have to keep deconstructing this BT. We have a deconstructor for BT it’s the one we are currently in the process of writing, so add a call back to bt-fn
4 the node’s right sub-tree which is a BT again. So we have to keep deconstructing this BT. We have a deconstructor for BT it’s the one we are currently in the process of writing, so add a call back to bt-fn

Observer how there are two recursive calls just like there are two recursive definitions in our BT data definition

Design Rule
The structure of our code follows the structure of our data!

Now that we have a data definition for BT let’s try and design a program that will take in a BT and return the sum of all the values in the BT

;;;; Signature:
;; bt-sum: BT -> Number
;;;; Purpose:
;; GIVEN: a binary tree
;; RETURNS: the sum of the binary trees values


(define LEAF (make-leaf))

;;;; Examples:
;; (bt-sum LEAF) => 0
;; (bt-sum (make-node 1 LEAF LEAF)) => 1
;; (bt-sum (make-node 2 (make-node 1 LEAF LEAF)
;;                      (make-node 3 LEAF LEAF)))
;; => 6


;;;; Function Definition:
(define (bt-sum bt)
  (cond
    [(leaf? bt) 0] (1)
    [(node? bt) (+ (node-value bt)        (2)
                   (bt-sum (node-left bt)) (3)
                   (bt-sum (node-right bt)))])) (4)


;;;; Tests:
(check-expect (bt-sum LEAF) 0)
(check-expect (bt-sum (make-node 1 LEAF LEAF)) 1)
(check-expect (bt-sum (make-node 2 (make-node 1 LEAF LEAF)
                                 (make-node 3 LEAF LEAF)))
              6)
1 when we are given a leaf then the sum is 0
2 when we are given a node we would like to extract the number stored in the slot value and add it to
3 the sum of our left sub-tree and
4 the sum of our right sub-tree.

Observer how there are two recursive calls just like there are two recursive calls in our deconstructor template

Design Rule
The structure of our code follows the structure of our data!

Binary Search Trees

Another popular variation of the Binary Tree is the Binary Search Tree (BST). A BST is similar to a BT but it also has to satisfy the following condition

For each node in the BST that is not a leaf node the value stored at the node \(v\) is

  1. greater than all values found in the left sub_tree, and

  2. less than all the values found in the right sub-tree.

Animations and big-bang