简体   繁体   中英

Getting the sum of the elements in the tree in Scheme

Write a procedure, (fold-right-tree op id tree) , that gathers together the leaves of the tree using op, analogous to fold-right on lists. So if tree has value

(((1 2)
  3)
 (4
  (5 6))
 7
 (8 9 10))

then

(fold-right-tree + 0  tree)

has value 55.

--I wanted to define code which sums all element in tree

 ;;----------

    (#%require racket)
    (define nil empty) 


    (define (reduce op init lst)
      (if (null? lst)
          init
          (op (car lst)
              (reduce op init (cdr lst)))))

    (define fold-right reduce)


    (define (sum-list lst)
      (if (null? lst) 0
          (+ (car lst) (sum-list (cdr lst)))
        ))

(define (leaf? x)
  (not (pair? x)))


    (define (fold-right-tree op init tree)
        (lambda (tree)
          (if (null? tree)
              0
              (if (leaf? tree)
                  (sum-list (list tree))
                  (fold-right op init (map fold-right-tree op init tree))))))


    (fold-right-tree (lambda (x,y) (+ x y)) 0 '((1) (2 3 4) (((5)))) )

Output should return sum of tree elements, but returns #<procedure>

what is my problem in it?

I also tried this one but this time I got Error for mapping

(define (fold-right-tree op init tree)
      (if (null? tree)
          0
          (if (leaf? tree)
              (fold-right op init (list tree))
              (+ (fold-right-tree op init (map car tree)) (fold-right-tree op init (map cdr tree))))))


(fold-right-tree sum 0 '((1) (2 3 4) (((5)))) )

From the problem specification, you could simply get all the leaves of the tree (with the flatten function) and then apply the relevant fold operation, like in:

(define (fold-right-tree op id tree)
  (foldr op id (flatten tree)))

(fold-right-tree + 0 '((1) (2 3 4) (((5)))))  ; => 15

This has been tested in Dr.Racket.

With suitable accessors & predicates for trees ( leaf? , empty-tree? , left-subtree & right-subtree ) then the obvious definition is:

(define (fold-right-tree op accum tree)
  (cond
    [(empty-tree? tree)
     accum]
    [(leaf? tree)
     (op accum tree)]
    [else (fold-right-tree op
                           (fold-right-tree op accum (right-subtree tree))
                           (left-subtree tree))]))

This has the advantage that it is completely agnostic about tree representation: all it knows is the names of the accessors. Indeed you could make it really agnostic:

(define (fold-right-tree op init tree
                         #:empty-tree? (empty? empty-tree?)
                         #:leaf? (lief? leaf?)
                         #:left-subtree (left left-subtree)
                         #:right-subtree (right right-subtree))
  (let frt ([a init] [t tree])
    (cond
      [(empty? t) a]
      [(lief? t) (op a t)]
      [else (frt (frt a (right t)) (left t))])))

Now it will walk any kind of binary tree.


Here are suitable definitions for trees which are in fact made of conses:

;;; Tree abstraction
;;;
(define (leaf? treeish)
  (not (pair? treeish)))

(define empty-tree? null?)
(define left-subtree car)
(define right-subtree cdr)

(define cons-tree cons)
(define empty-tree '())

(define (->tree listy
                #:empty-tree (empty empty-tree)
                #:cons-tree (ctree cons-tree))
  ;; turn a cons tree into a tree
  (cond
    [(null? listy) empty]
    [(pair? listy) (ctree (->tree (car listy))
                          (->tree (cdr listy)))]
    [else listy]))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM