I have already defined helper functions to be:
;; returns value of node
(define (value node)
(if (null? node) '()
(car node)))
;; returns left subtree of node
(define (left node)
(if (null? node) '()
(cadr node)))
;; returns right subtree of node
(define (right node)
(if (null? node) '()
(caddr node)))
and I am trying to write a function leaves that returns a list with the leaves of the tree in order of left to right.
(define (leaves tree)
(if (and (?null (left tree)) (?null (right tree)))
???
(leaves (left tree)) (leaves (right tree))))
but that is as far as I can get
ex: (leaves '(1 (2 () ()) (3 () ()))) should evaluate to '(2 3)
In what you have so far, the ??? is going to need to evaluate to the value of the leaf, ie. (value node) because it is the base case of your iteration. Also, you're going to need to combine the values you get back from the base case in your iteration case. list is usually a good first candidate to try when you need to combine multiple results cons is usually my second try. Taking those suggestions, your leaves function looks like this:
(define (leaves tree)
(if (and (null? (left tree)) (null? (right tree)))
(value tree)
(list (leaves (left tree)) (leaves (right tree)))))
which, when run on your sample of (leaves '(1 (2 () ()) (3 () ()))) does indeed evaluate to (2 3).
HOWEVER; YOU'RE NOT DONE! We're only testing with 1 level of recursion. What if we make a bigger tree? Something like: (leaves '(1 (2 (4 () ()) (5 () ())) (3 (6 () ()) (7 () ())))) Running this gives ((4 5) (6 7)). Those are the right values in the right order, but we have too much structure in there, too many parenthesis. This is a typical problem you will encounter throughout your scheme career, so let me explain why it happens, and how you can go about attacking the problem.
If look at the two branches of our if form, you'll notice that (value tree) returns an atom, or a number in this case. The else branch takes two of ??? and turns it into a list of ???. We're going to be executing the else branch multiple times - any time we're not in the base case. This means we're going to continue to wrap, and wrap, and wrap into a deeper and deeper list structure. So here's what we do about it.
Lets return a list in our base case, and keep our list flat in the recursion case. To return a list in our base case it is as simple as returning (list (value tree)) instead of just (value tree). In the recursion case, we need a function that takes 2 lists and combines them without making a deeper list. Such a function does exist - append. So let's look at what our leaves function looks like now:
(define (leaves tree)
(if (and (null? (left tree)) (null? (right tree)))
(list (value tree))
(append (leaves (left tree)) (leaves (right tree)))))
Intermezzo - Test cases
Racket has test suite library that has a very low barrier to entry called rackunit. Let's throw together a few quick test cases at the bottom of the file.
(require rackunit)
;;empty tree
(check-equal? (leaves '()) '())
;;simple balanced tree
(check-equal?
(leaves '(1 (2 () ()) (3 () ())))
'(2 3))
;;larger balanced tree
(check-equal?
(leaves '(1 (2 (4 () ()) (5 () ())) (3 (6 () ()) (7 () ()))))
'(4 5 6 7))
;;unbalanced tree
(check-equal?
(leaves '(1 (2 (4 () ()) ()) (3 () ())))
'(4 3))
Recently, racket has added support for submodules and specific support for test submodules if you are curious and want to look into them.
Back to our leaves problem. Running our tests, we notice our function doesn't behave well on unbalanced trees. We get extra ()s when we have a node that only has 1 leaf. That is because we are traversing both the left and the right subtrees whenever we're at a node that isn't a leaf. What we really need are two more cases in our if. We could nest the ifs, but scheme's cond form makes better sense.
Now, the template we're aiming to fill out is:
(define (leaves tree)
(cond [(leaf? tree) (...)]
[(and (has-left? tree) (has-right? tree))
(...)]
[(has-left? tree) (...)]
[(has-right? tree) (...)]
[else (error "should never get here")]))
I'll stop there in-case this is homework, and to give you the satisfaction of understanding and solving this the rest of the way. I hope my explanations have given you more direction that just "here's the code" answers.
Well this seems like you're doing Breadth First Search but with the alteration that you don't print yourself if you have two children (or just one, if you don't want to print nodes that only have one child).
I would aim for solving that first, and then changing your solution to that to solve this problem.
(define (list-of-leaves tree)
(if(leaf? tree)
(list (node tree))
(cond((right-branch-only? tree)(list-of-leaves (right-branch tree)))
((left-branch-only? tree)(list-of-leaves (left-branch tree)))
(else(append (list-of-leaves (left-branch tree))
(list-of-leaves (right-branch tree)))))))
Related
im trying to find the max value in a tree, but I'm having trouble understanding the recursion part of it.
what I have so far
(define mytree '(10 (5(4(2 ()()) (22()())) (21(15()()) (23 ()()))) (11(6()())(13()()))))
(define (leaf mytree)
(and(null?(cadr mytree)) (null? (caddr mytree))))
(define (maxval mytree)
(if (null? mytree)
mytree
(max (leaf(maxval (cadr mytree))) (leaf(maxval (caddr mytree))))))
(maxval mytree)
I'm trying to make the leaf function go through every number in the tree until it gets to the bottom numbers, where it will find the greatest value.
Formatting
Indent code, align subtrees, add space
Name predicate with ? at the end
Use tree instead of mytree
Define abstractions (left-child, right-child instead of cadr-soups)
This is more readable:
(define mytree
'(10 (5 (4 (2 () ())
(22 () ()))
(21 (15 ()())
(23 ()())))
(11 (6 () ())
(13 () ()))))
(define (tree-value tree)
(car tree))
(define (left-child tree)
(cadr tree))
(define (right-child tree)
(caddr tree))
(define (leaf? tree)
(and (null? (left-child tree)
(null? (right-child tree))))
(define (maxval tree)
(if (null? tree)
'()
(max (leaf? (maxval (left-child tree)))
(leaf? (maxval (right-child tree))))))
Recursive algorithm
The maximum value of a tree (maxvalue tree) is the maximum value among:
the value associated with the tree: (tree-value tree)
the maximum value of its left subtree: (maxvalue (left-child tree))
the maximum value of its right subtree: (maxvalue (right-child tree))
The degenerate case (base case) where a tree has no child is to return the value associated with the tree.
Your current algorithm does not do that. In particular:
Why is the result of leaf? given to max?
Why don't you check the value rooted at current tree?
You should be able to translate the above in terms of code. This should look roughly like this (untested):
(define (maxval tree)
(if (leaf? tree)
(tree-value tree)
(max (tree-value tree)
(maxval (left-child tree))
(maxval (right-child tree)))))
Short version: you need a data definition, and test cases.
Your data definition should probably read
;; a binary tree is either:
;; -- <you fill in this part>, or
;; -- <you fill in this part too>
Then, you need test cases.
write a test case for both cases of your data definition.
This should answer your question for you.
(In general, the stepper can be helpful, but in this case, I think the problem starts earlier.)
Defined in Scheme one (sumanodos-pareja-tree tree) function that takes a tree
generic and returns a new generic tree where each datum is a pair containing the data
Original (left) and the sum of its children nodes (right):
I do this:
(define (sumanodos-pareja-tree tree)
(let ((bosque-sumados (map sumanodos-pareja-tree (hijos-tree tree))))
(make-tree (cons (dato-tree tree) (suma-datos-raiz bosque-sumados))
bosque-sumados)))
(define (suma-datos-raiz bosque-sumados)
(if (null? bosque-sumados) 0
(let ((primer-arbol (car bosque-sumados)))
(+ (car (dato-tree primer-arbol))
(cdr (dato-tree primer-arbol))
(suma-datos-raiz (cdr bosque-sumados))))))
(define tree22 '(2 (7 (1 (10) (4))
(5))
(6 (2 (3)))
(4)))
(sumanodos-pareja-tree tree22)
But it returns this error;
cons: second argument must be a list, but received 2 and 42
as I can do?
This is a restriction of some Racket learning languages. Use list instead of cons.
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)))))
Im struggling with this problem for over 2 days now and still somehow I cannot solve it.
I have to write a function in SCHEME that takes a list in a tree and displays items in sorted order.
The way I define trees is '(6 (left... ) (right...))
My function to choose a tree:
(define (tree-sort tree)
(cond ((null? tree) '())
((> (car tree) (cadr tree))
(tree-sort (cadr tree)))
(else
(tree-sort (caddr tree))))
)
So I guess I should also have a function that sorts the most indepth list?
I really dont get it and this is the last time I will ever have to deal with scheme. I have never used stackoverflow so please excuse me if the formating is wrong.
Kindly thank you!
Now that you clarified that the tree is already sorted, then you're looking for an in-order traversal of the tree, which returns a sorted list of the elements - I'm assuming that you're interested in a list as the output, because of the base case shown in the question. Try something like this:
(define (tree-sort tree)
(if (empty-tree? tree)
'()
(append (tree-sort (left-subtree tree))
(list (value tree))
(tree-sort (right-subtree tree)))))
Use the appropriate procedures for testing if the tree is empty and for accessing each node's value, left and right subtrees. The above procedure will return a sorted list with the trees' values.
My friend and I are currently working on creating a Binary Search Tree in Scheme. We cannot get it to save what we have inserted. My professor said we are to use set-car! (cdr ( for the left subtree somehow, but I don't know where exactly to put it in. We are supposed to use set-car! (cddr ( for the right subtree also.
We have done all of this so far correctly, but we just need help making it save our inserted nodes.
Code:
(define make-empty-BST '())
;create function to see if BST is empty
(define (emptyBST? BST) (null? BST))
;make non-empty BST with explicit list implementation
(define (make-BST root left-subtree right-subtree)
(list root left-subtree right-subtree))
;helper get root function
(define (getRoot BST) (car BST))
;helper get left subtree function
(define (getLeftsubTree BST) (cadr BST)) ;(car (cdr tr))
;helper get right subtree function
(define (getRightsubTree BST) (caddr BST)) ;(car (cdr (cdr tr)))
;Checks to see if a leaf is empty
(define (emptyleaf? BST) (and (null? (getLeftsubTree BST)) (null? (getRightsubTree BST))))
;inserts an item into the BST
(define (BST-insert BST item)
(cond
((emptyBST? BST) ;if empty, create a new root with given item - use empty lists for left and right subtrees
(make-BST item make-empty-BST make-empty-BST))
((< item (getRoot BST)) ;if item less than root, add to left subtree
(make-BST (getRoot BST)
(BST-insert (getLeftsubTree BST) item) ;recursion
(getRightsubTree BST)))
((> item (getRoot BST))
(make-BST (getRoot BST)
(getLeftsubTree BST)
(BST-insert (getRightsubTree BST) item)))
(else BST))) ; it's already in BST, do nothing
Since this sounds like an assignment, I don't want to provide the exact code that you need, but I'll show two functions that could be said to replace the nth element of list. The first will be analogous to yours, in that it returns a new list and doesn't modify the input list. The second will modify the input list.
(define (replace-nth n element list)
;; return a new list like list, but whose
;; nth element is element
(if (= n 0)
(cons element (cdr list))
(cons (car list) (replace-nth (- n 1) element (cdr list)))))
(let ((l (list 1 2 3 4 5 6)))
(display (replace-nth 3 'x l)) ; prints (1 2 3 x 5 6)
(display l)) ; prints (1 2 3 4 5 6)
The first returns a new list, but doesn't modify the input list. It creates a new list using cons applied to part of the old list and some new value. This is similar to what you're doing when you insert by creating a new tree that has the new value. The tree that you've passed in won't have it, but the tree will.
(define (set-nth! n element list)
;; set the nth element of list to be element
(if (= n 0)
(set-car! list element)
(set-nth! (- n 1) element (cdr list))))
(let ((l (list 1 2 3 4 5 6)))
(display (set-nth! 4 'x l)) ; prints #<void>
(display l)) ; prints (1 2 3 4 x 6)
The second modifies the list that is passed to it. Its return value isn't quite so important, because the structure passed into it actually gets modified. This is more like what you'd want to do with your insert function. You need to recurse until you get to the correct node in the tree, and the set its left or right child to be a new tree containing just the new element.
You've provided 'get' procedures, why not start by providing a 'set' procedure? Doing so works towards completing your 'tree/node abstraction' and gives you a base set of functions to try to use in your 'insert' procedure.
(define (setLeftsubTree BST left)
(set-car! (cdr BST) left))
(define (setRightsubTree BST right)
(set-car! (cddr BST) right))
Now, in your insert code, when you want to 'go left' but there is no left, call setLeftsubTree with a newly created leaf node.