;;; ======================================================= ;;; CMPU-365, Fall 2014 ;;; Solutions to Asmt 1 -- in Scheme ;;; ======================================================= (printf "==========================~%") (printf " CMPU-365, Fall 2014~%") (printf " Asmt. 1~%") (printf " Solutions in Scheme!~%") (printf "==========================~%~%") (printf "The sample bin-trees from 'bintrees-in-scheme.txt'...~%~%") (load "bintrees-in-scheme.txt") ;;; ------------ ;;; (1) ;;; ------------ (problem "1: INSERT-NUMS") ;;; INSERT ;;; ----------------------------------------- ;;; INPUTS: NUM, a number ;;; TREE, a binary tree ;;; OUTPUT: A tree just like TREE, except it contains ;;; a node with DATUM = NUM. In addition, the ;;; new node is inserted to the LEFT of pre-existing ;;; nodes with bigger numbers, and to the right of ;;; pre-existing nodes with smaller numbers. ;;; If NUM already appears in the tree, then the ;;; tree is returned unchanged. (define insert (lambda (num tree) (cond ;; Base Case: TREE is empty. ((mt-tree? tree) ;; Create a new tree with one node, where DATUM = NUM. (make-node *mt-tree* num *mt-tree*)) ;; NOTE: In the rest of the cases, TREE is assumed to be ;; non-empty (i.e., an instance of the NODE struct). ;; Base Case 2: NUM = DATUM at root of TREE ;; (i.e., NUM is already in the TREE) ((= num (node-datum tree)) ;; Return the TREE unchanged... tree) ;; Recursive Case 1: NUM < DATUM at root of TREE ((< num (node-datum tree)) ;; Return a tree just like TREE, except that NUM ;; is inserted into left-hand sub-tree (make-node (insert num (node-lefty tree)) (node-datum tree) (node-righty tree))) ;; Recursive Case 2: NUM > DATUM at root of TREE (#t ;; Return a tree just like TREE, except that NUM ;; is inserted into right-hand sub-tree (make-node (node-lefty tree) (node-datum tree) (insert num (node-righty tree))))))) ;;; INSERT-NUMS ;;; ======================================= ;;; INPUTS: NUMS, a list of numbers ;;; TREE, a binary tree ;;; OUTPUT: A tree just like TREE, except that all of the ;;; numbers in NUMS have been inserted into TREE. ;;; ------------------------------------------------ ;;; NOTE: TREE is an accumulator! (define insert-nums (lambda (nums tree) (cond ;; Base Case: No more NUMS to insert ((null? nums) ;; Return accumulated tree! tree) ;; Recursive Case: (#t ;; Insert the REST of the NUMS into the tree ;; that results from inserting FIRST NUM into TREE (insert-nums (rest nums) (insert (first nums) tree)))))) (tester '(print-bin-tree (insert-nums '(5 2 3 8 9 2 16 4 3 0 12) *mt-tree*))) (tester '(print-bin-tree (insert-nums '(50 25 75 12 37 62 88 5 17 28 30 42 99 52 85 57 77 72 60) *mt-tree*))) ;;; CREATE-BIN-TREE ;;; -------------------------------------- ;;; Just a wrapper for INSERT-NUMS (define create-bin-tree (lambda (nums) (insert-nums nums *mt-tree*))) (tester '(print-bin-tree (create-bin-tree '(4 3 8 9 2 4 5 4 6)))) (tester '(print-bin-tree (create-bin-tree ()))) (tester '(print-bin-tree (create-bin-tree '(1 2 3 4)))) (tester '(print-bin-tree (create-bin-tree '(4 3 2 1)))) (tester '(print-bin-tree (create-bin-tree '(2 4 1 3)))) ;;; ----------- ;;; (2) ;;; ----------- (problem "2: DF listing") ;;; GEN-DEPTH-FIRST-LISTING-ACC ;;; ====================================================== ;;; INPUTS: TREE, a binary tree ;;; ACC, a list-based accumulator ;;; OUTPUT: This function accumulates the nodes in TREE by ;;; visiting them in a depth-first traversal. Thus, ;;; when called with ACC empty, it returns a list of ;;; the numbers in TREE where the order is the *reverse* ;;; of that determined by a depth-first traversal (because ;;; nodes visited later are CONSed onto the front of the ;;; accumulator). (define gen-depth-first-listing-acc (lambda (tree acc) (cond ;; Base Case: TREE is empty, so return the accumulator ((mt-tree? tree) acc) ;; Recursive Case: TREE is non-empty (i.e., it's a NODE struct) (#t ;; So... accumulate the nodes from the right-hand sub-tree ;; and then feed those in as the initial accumulator when ;; accumulating the nodes in the left-hand sub-tree. ;; Oh, and don't forget about the DATUM at *this* node! (gen-depth-first-listing-acc (node-righty tree) (gen-depth-first-listing-acc (node-lefty tree) (cons (node-datum tree) acc))) )))) ;;; GEN-DEPTH-FIRST-LISTING ;;; ---------------------------------------------------------- ;;; INPUT: TREE, a binary tree ;;; OUTPUT: A list of the numbers in TREE, whose order is ;;; determined by a depth-first traversal (e.g., the number at ;;; the root node is the first item in the returned list, ;;; the number at the rightmost node is the last item). (define gen-depth-first-listing (lambda (tree) ;; Just call the accumulator-based helper with the accumulator ;; initially empty --- oh, and reverse the order! (reverse (gen-depth-first-listing-acc tree ())))) (tester '(gen-depth-first-listing *mt-tree*)) (tester '(gen-depth-first-listing (create-bin-tree '(1 2 3 4)))) (tester '(gen-depth-first-listing (create-bin-tree '(4 3 2 1)))) (tester '(gen-depth-first-listing (create-bin-tree '(2 4 3 1)))) (tester '(gen-depth-first-listing big-tree))