Beginner Scheme: Turning Binary Search Trees into lists - scheme

I am having trouble with binary search trees and turning them into lists.
(define-struct node (key val left right))
;; A binary search tree (bst) is either
;; empty, or
;; a structure (make-node k v l r), where
;; k is a number (the key),
;; v is a string (the value),
;; l is a bst, where every key in l is less than k, and
;; r is a bst, where every key in r is greater than k.
Can anybody give me hints on how to approach this question?
Create a function bst that consumes a binary search tree and returns a list of all the strings in the value field of the binary search tree nodes and the list must be in descending order based on the key values in the binary search tree.
;;Examples: (bst (make-node 4 "James" (make-node 2 "Kien" empty empty)
;;(make-node 5 "Jack" empty (make-node 11 "Cole" empty empty)))) => (list "Cole" "Jack" "James" "Kien")
Thanks!

Basically, you have to visit all the nodes in the tree using a reverse in-orden traversal (right subtree / value / left subtree), while at the same time creating a list with the answer. Something along these lines:
(define (tree->list tree)
(if (empty? tree)
empty
(append (tree->list (node-right tree))
(cons (node-val tree)
(tree->list (node-left tree))))))
It works as expected:
(define bst
(make-node 4 "James"
(make-node 2 "Kien" empty empty)
(make-node 5 "Jack" empty
(make-node 11 "Cole" empty empty))))
(tree->list bst)
=> (list "Cole" "Jack" "James" "Kien")

(define (tree->list tree)
(if(leaf? tree)
(list (node tree))
(cond((right-branch-only? tree)(append (list(node tree))
(tree->list (right-branch tree))))
((left-branch-only? tree)(append (list(node tree))
(tree->list (left-branch tree))))
(else(append (list (node tree))
(append (tree->list (left-branch tree))
(tree->list (right-branch tree))))))))

Related

how do you sum tree in scheme

;; A [BT X] is one of
;; - 'leaf
;; - (make-node X [BT X] [BT X])
(define-struct node (val left right))
;; interpretation: represents a node with a value
;; a left and right subtree
(define (tree-sum tree)
(cond
[(symbol=? tree 'leaf) ...] ;; the value remains same
[(node? tree)
(+ (tree-sum (node-val tree))
(tree-sum (node-left tree))
(tree-sum (node-right tree)))]))
not quite sure if i'm on the right track.
Normally, A pair tree is either
a leaf (not a pair), or
a pair, whose car and cdr values are pair-trees.
recursive summing procedure will have to deal with these two cases:
a numbers, i.e., leaves of a tree of numbers, and
pairs, in which case it should sum the left and right subtrees, and add those sums together.
Therefore,
(define (pair-tree-sum pair-tree)
(cond
[(number? pair-tree)
pair-tree]
[else
(+ (pair-tree-sum (car pair-tree))
(pair-tree-sum (cdr pair-tree)))]))
You can split the function into two parts - one that converts the tree into a list of numbers, and another that just uses foldl with that list, and foldl has the advantage of automatically doing the summation as an accumulator.
(define (tree->list tree)
(if (pair? tree)
(append (tree->list (car tree))
(tree->list (cdr tree)))
(list tree)))
(define (tree-sum tree)
(foldl + 0 (tree->list tree)))
You first need to check if the tree is empty, then if its not a list, else you call the function sum to the car of the list, and add to the cdr of the list.
(define (sum tree)
(cond [(empty? tree) 0]
[(not (list? tree)) (if (number? tree) tree 0)]
[else (+ (sum (first tree)) (sum (rest tree)))]))

scheme consumes BT tree and returns the elements of the tree as a list of strings

You are provided with the following definition for binary tries
(define-struct leaf ())
;; interpretation: represents a leaf on a BT, a node with no children
(define-struct node (word left right))
;; interpretation: represents a node on a BT with a word, a left and a right
;; subtree
;; A BinaryTree (BT) is one of
;; - (make-leaf)
;; - (make-node String BT BT)
Design the program bt->los that consumes a BT tree and returns the elements of the tree as a list of strings. At each node your function should
1.process the left sub tree
2.process the word at this node
3.process the right sub tree
;; bt->los: tree -> los
;; consumes a BT tree and returns the elements of the tree as a list of strings.
(define (bt->los tree)
(cond
[(leaf? tree) ""]
[(node? tree)
(append (bt->los(list (node-left tree)))
(list (node-word tree))
(bt->los (list (node-right tree))))]))
I'm stuck here. Should have missed something. Don't we need recursion here?
Output should be like,
(define bt-abc (make-node "b"
(make-node "a" (make-leaf) (make-leaf))
(make-node "c" (make-leaf) (make-leaf))))
(bt->los bt-abc) (cons "a" (cons "b" (cons "c" empty)))
You are very close here. Just a couple of mistakes.
(define (bt->los tree)
(cond
[(leaf? tree) empty]
[(node? tree)
(append (bt->los (node-left tree))
(list (node-word tree))
(bt->los (node-right tree)))]))
First, you are constructing a list of string. Because it is a list, your base case should be empty. not "". Second, each node, already represents a BT, there is no need to list it. And bt->los returns
a list. With this simple changes, it works as expected for you test case.

scheme determine a string inside a tree list or not

Here's my data definition,
(define-struct leaf ())
;; interpretation: represents a leaf on a BT, a node with no children
(define-struct node (word left right))
;; interpretation: represents a node on a BT with a word, a left and a right
;; subtree
;; A BinaryTree (BT) is one of
;; - (make-leaf)
;; - (make-node String BT BT)
;; bt-has? : BT String -> Boolean
;; given a BT tree and a String w and returns true if w is in the tree
;; and false otherwise
(define (bt-has? tree w)
(cond
[(leaf? tree) (bt-has? tree w)]
[(and (node? tree)
(string=? w (node-word (first tree))))
(bt-has? (rest tree) w) ]))
I don't know why it keeps giving the all question results were false error code.
(string=? w (node-word (first tree))))
seems right to me. Any suggestion?
I guess the mistake i made was BT(tree) is a structure not a list so that's why this error code pops.
Here's a revised version.
;; bt-has? : BT String -> Boolean
;; given a BT tree and a String w and returns true if w is in tree
;; and false otherwise
(define (bt-has? tree w)
(cond
[(leaf? tree) false]
[else
(and (node? tree)
(string=? w (node-word tree))
(bt-has? (node-left tree) w)
(bt-has? (node-right tree) w))]))
;; tests
(check-expect (bt-has? (make-node "a" (make-leaf) (make-node "b" (make-leaf) (make-leaf) "a")) true)
(check-expect (bt-has? (make-node "a" (make-leaf) (make-leaf)) "b")false)
(check-expect (bt-has? (make-leaf) "a") false)

Confused about binary search trees (Scheme)

I have a problem that I need to complete:
We can represent a nonempty binary tree by list (root left_subtree
right_subtree) and the empty tree by the empty list. Each binary
search tree with integer labels can be considered representing a set
of integers. Write a function which, given a set of integers S as a
bst and an integer x, returns both the set of all the integers less
than x and that of all the integers greater than x as bst’s. Use a
pair rather than a list to represent the resulting sets.
I'm very new to Scheme. I've built trees using SML as well as prolog, but can't seem to get a hold of what I need to do for Scheme. Could anyone help me out and guide me towards this goal? Is my tree suppose to just look like this?
(list value left right)
Yes, that's one way to define a tree. Just so long as you make a proper ADT and use it consistently, it shouldn't matter after you've defined it.
(define (make-tree root left right)
(list root left right))
(define (right tree)
(caddr tree))
(define (left tree)
(cadr tree))
(define (root tree)
(car tree))
(define (empty-tree? tree)
(null? tree))
(define empty-tree '())
(define (leaf? tree)
(and (empty-tree? (left tree)) (empty-tree? right tree)))
(define (split-tree-at tree x)
(let ((less ...)
(more ...))
(cons less more))
(define (in-tree-below-x tree x) ;;assuming a sorted tree
(cond ((empty-tree? tree) (empty-tree))
((>= (root tree) x)
(in-tree-below (left tree) x))
(else (make-tree (root tree)
(left tree)
(in-tree-below-x (right tree) x)))))

Binary trees in scheme

How would I count how many nodes a tree has?
;;; A Binary is one of:
;;; - Number
;;; - (make-node BT BT)
(define-struct node (left right))
(define tree1 (make-node (make-node 10 9)
(make-node 3
(make-node 1 5))))
(define (how-many? nd)
(cond
[(number? nd)....]
[(node? n)
(..... (how-many? (node-left nd))
(how-many? (node-right nd)))]))
so for tree1 I should get
(check-expect (how-many? tree1) 5)
I think I got the template right. If it's a number, you should return 1. But if it's a node, what type of function should I put in the dotted lines?
This is somewhat similar to how you'd process a list. The difference? that now you'll go to the "left" and to the "right" of each node, instead of going just to the "rest". Other than that, the same ideas apply:
(define (how-many? nd)
(cond
[(number? nd) <???>] ; if it's a leaf, then how many numbers does it have?
[(node? nd)
(<???> (how-many? (node-left nd)) ; how do we combine the results?
(how-many? (node-right nd)))]))
You got the base case right, as I can see in the question. The recursive case is simple! remember, how did we combine the results when we were adding the elements in a list? here's the same thing, it's just that we combine the results from the left and from the right subtrees.

Resources