set: add insert multiple test
This commit is contained in:
parent
f160ecaae1
commit
931cd50159
142
set.scm
142
set.scm
|
@ -113,7 +113,7 @@
|
||||||
(lighter-dir (%set:invdir heavier-dir)))
|
(lighter-dir (%set:invdir heavier-dir)))
|
||||||
(let ((heavy-heavy (%set:get heavier heavier-dir))
|
(let ((heavy-heavy (%set:get heavier heavier-dir))
|
||||||
(heavy-light (%set:get heavier lighter-dir)))
|
(heavy-light (%set:get heavier lighter-dir)))
|
||||||
(if (<= (abs (%avl:diff heavy-light lighter) 1))
|
(if (<= (abs (%set:height-diff heavy-light lighter)) 1)
|
||||||
(let ((node (%set:node val
|
(let ((node (%set:node val
|
||||||
heavier-dir heavy-light
|
heavier-dir heavy-light
|
||||||
lighter-dir lighter)))
|
lighter-dir lighter)))
|
||||||
|
@ -134,17 +134,13 @@
|
||||||
node
|
node
|
||||||
(%set:rotate node heavier-dir)))))))))
|
(%set:rotate node heavier-dir)))))))))
|
||||||
|
|
||||||
;;; JOIN takes two trees and the data for a node, such that all nodes
|
|
||||||
;;; in LEFT are less than or equal to VAL, and all nodes in RIGHT are
|
|
||||||
;;; greater than or equal to VAL, and outputs a balanced binary search
|
|
||||||
;;; tree.
|
|
||||||
(define set:join
|
(define set:join
|
||||||
(lambda (left val right)
|
(lambda (val dir1 node1 dir2 node2)
|
||||||
(let ((diff (%set:diff left right)))
|
(let ((diff (%set:height-diff node1 node2)))
|
||||||
(cond
|
(cond
|
||||||
((> diff 1) (%set:join left val right '<))
|
((> diff 1) (%set:join node1 val node2 dir1))
|
||||||
((< diff -1) (%set:join right val left '>))
|
((< diff -1) (%set:join node2 val node1 dir2))
|
||||||
(else (set:node val '< left '> right))))))
|
(else (%set:node val dir1 node1 dir2 node2))))))
|
||||||
|
|
||||||
(define set:join2
|
(define set:join2
|
||||||
(letrec
|
(letrec
|
||||||
|
@ -153,20 +149,19 @@
|
||||||
(if (null? left)
|
(if (null? left)
|
||||||
right
|
right
|
||||||
(let ((split-last-tree (split-last left)))
|
(let ((split-last-tree (split-last left)))
|
||||||
(set:join (bst:get split-last-tree '<)
|
(set:join (%set:get split-last-tree '=)
|
||||||
(bst:get split-last-tree '=)
|
'< (%set:get split-last-tree '<)
|
||||||
right)))))
|
'> right)))))
|
||||||
(split-last
|
(split-last
|
||||||
(lambda (tree)
|
(lambda (tree)
|
||||||
(let ((right (set:get tree '>)))
|
(let ((right (%set:get tree '>)))
|
||||||
(if (null? right)
|
(if (null? right)
|
||||||
tree
|
tree
|
||||||
(let ((last (split-last right)))
|
(let ((last (split-last right)))
|
||||||
(bst:node (set:get last '=)
|
(%set:node (%set:get last '=)
|
||||||
(join (set:get tree '<)
|
(set:join (%set:get tree '=)
|
||||||
(set:get tree '=)
|
'< (%set:get tree '<)
|
||||||
(set:get last '<))
|
'> (%set:get last '>)))))))))
|
||||||
'())))))))
|
|
||||||
join2))
|
join2))
|
||||||
|
|
||||||
;;; ;;;;;;;;;;;;;;;;;
|
;;; ;;;;;;;;;;;;;;;;;
|
||||||
|
@ -187,7 +182,7 @@
|
||||||
(let ((dir (<=> (%set:get tree '=) data)))
|
(let ((dir (<=> (%set:get tree '=) data)))
|
||||||
(if (eq? dir '=)
|
(if (eq? dir '=)
|
||||||
tree
|
tree
|
||||||
(loop (set:get tree dir))))))))
|
(loop (%set:get tree dir))))))))
|
||||||
(loop tree)))))
|
(loop tree)))))
|
||||||
|
|
||||||
;;; (SET:INSERT <=>) generates an insert function for comparison function
|
;;; (SET:INSERT <=>) generates an insert function for comparison function
|
||||||
|
@ -205,17 +200,16 @@
|
||||||
(if (null? tree)
|
(if (null? tree)
|
||||||
node
|
node
|
||||||
(let ((dir (<=> (%set:get tree '=)
|
(let ((dir (<=> (%set:get tree '=)
|
||||||
(%set:get node '=)))
|
(%set:get node '=))))
|
||||||
(left (%set:get tree '<))
|
|
||||||
(right (%set:get tree '>)))
|
|
||||||
(if (eq? dir '=)
|
(if (eq? dir '=)
|
||||||
(begin
|
(begin
|
||||||
(set! found tree)
|
(set! found tree)
|
||||||
(set:node (set:get node '=)
|
(%set:node (%set:get node '=)
|
||||||
'< left '> right))
|
'< left '> right))
|
||||||
(join (set:node (%set:get tree '=)
|
(let ((invdir (%set:invdir dir)))
|
||||||
dir (loop left)
|
(set:join (%set:get tree '=)
|
||||||
(set:invdir dir) right))))))))
|
dir (loop (%set:get tree dir))
|
||||||
|
invdir (%set:get tree invdir)))))))))
|
||||||
(let ((newtree (loop tree)))
|
(let ((newtree (loop tree)))
|
||||||
(cons newtree found)))))))
|
(cons newtree found)))))))
|
||||||
|
|
||||||
|
@ -235,16 +229,16 @@
|
||||||
(if (null? tree)
|
(if (null? tree)
|
||||||
node
|
node
|
||||||
(let ((dir (<=> (%set:get tree '=)
|
(let ((dir (<=> (%set:get tree '=)
|
||||||
(%set:get node '=)))
|
(%set:get node '=))))
|
||||||
(left (%set:get tree '<))
|
|
||||||
(right (%set:get tree '>)))
|
|
||||||
(if (eq? dir '=)
|
(if (eq? dir '=)
|
||||||
(begin
|
(begin
|
||||||
(set! found tree)
|
(set! found tree)
|
||||||
(set:join2 left right))
|
(set:join2 (%set:get tree '<)
|
||||||
(join (set:node (%set:get tree '=)
|
(%set:get tree '>)))
|
||||||
dir (loop left)
|
(let ((invdir (%set:invdir dir)))
|
||||||
(set:invdir dir) right))))))))
|
(set:join (%set:get tree '=)
|
||||||
|
dir (loop (%set:get tree dir))
|
||||||
|
invdir (%set:get tree invdir)))))))))
|
||||||
(let ((newtree (loop tree)))
|
(let ((newtree (loop tree)))
|
||||||
(cons newtree found)))))))
|
(cons newtree found)))))))
|
||||||
|
|
||||||
|
@ -260,11 +254,23 @@
|
||||||
((string>? x y) '>)
|
((string>? x y) '>)
|
||||||
(else '=)))))
|
(else '=)))))
|
||||||
|
|
||||||
|
(cond-expand
|
||||||
|
((and (not miniscm-unslisp) (not r7rs))
|
||||||
|
(define (list-set! lst n val)
|
||||||
|
(if (= n 0)
|
||||||
|
(set-car! lst val)
|
||||||
|
(list-set! (cdr lst) (- n 1) val)))))
|
||||||
|
|
||||||
(define map:string<=>
|
(define map:string<=>
|
||||||
(lambda (x y)
|
(lambda (x y)
|
||||||
(string<=> (car x) (car y))))
|
(string<=> (car x) (car y))))
|
||||||
|
|
||||||
(define %smap:insert (set:insert map:string<=>))
|
(define %smap:insert (set:insert map:string<=>))
|
||||||
|
|
||||||
|
;;; (SMAP:INSERT TREE KEY VAL) inserts (CONS KEY VAL) into TREE, and
|
||||||
|
;;; returns (CONS NEWROOT FOUND), where NEWROOT is the new root of
|
||||||
|
;;; the tree, and FOUND is #F if no element matching KEY was found,
|
||||||
|
;;; or the matching element if found.
|
||||||
(define smap:insert
|
(define smap:insert
|
||||||
(lambda (tree key val)
|
(lambda (tree key val)
|
||||||
(%smap:insert tree (%set:node (cons key val)
|
(%smap:insert tree (%set:node (cons key val)
|
||||||
|
@ -272,6 +278,8 @@
|
||||||
'> '()))))
|
'> '()))))
|
||||||
|
|
||||||
(define %smap:search (set:in map:string<=>))
|
(define %smap:search (set:in map:string<=>))
|
||||||
|
|
||||||
|
;;; (SMAP:SEARCH TREE KEY)
|
||||||
(define smap:search
|
(define smap:search
|
||||||
(lambda (tree key)
|
(lambda (tree key)
|
||||||
(%smap:search tree (cons key '()))))
|
(%smap:search tree (cons key '()))))
|
||||||
|
@ -287,6 +295,46 @@
|
||||||
(define smap:val
|
(define smap:val
|
||||||
(lambda (node) (cdr (%set:get node '=))))
|
(lambda (node) (cdr (%set:get node '=))))
|
||||||
|
|
||||||
|
;;; ;;;;;
|
||||||
|
;;; Tests
|
||||||
|
;;; ;;;;;
|
||||||
|
|
||||||
|
;;; LST is a list of elements of the form
|
||||||
|
;;; (KEY VAL ALREADY-IN)
|
||||||
|
;;; where ALREADY-IN is #F for an element not in the set, or the value
|
||||||
|
;;; that should be in the set.
|
||||||
|
|
||||||
|
(define %set:operate-all
|
||||||
|
(lambda (f tree lst)
|
||||||
|
(if (null? lst)
|
||||||
|
tree
|
||||||
|
(let ((key (list-ref (car lst) 0))
|
||||||
|
(val (list-ref (car lst) 1))
|
||||||
|
(already-in (list-ref (car lst) 2)))
|
||||||
|
(let ((insert-return (f tree key val)))
|
||||||
|
(cond
|
||||||
|
((and already-in (not (cdr insert-return)))
|
||||||
|
"should have been found")
|
||||||
|
((and already-in (not (equal? already-in
|
||||||
|
(smap:val (cdr insert-return)))))
|
||||||
|
"found is not correct")
|
||||||
|
(else (%set:operate-all f (car insert-return) (cdr lst)))))))))
|
||||||
|
|
||||||
|
(define %set:insert-all
|
||||||
|
(lambda (tree lst)
|
||||||
|
(%set:operate-all smap:insert tree lst)))
|
||||||
|
|
||||||
|
(define %set:search-all
|
||||||
|
(lambda (tree lst)
|
||||||
|
(%set:operate-all (lambda (tree key _)
|
||||||
|
(let ((search-res (smap:search tree key)))
|
||||||
|
(cons tree search-res))) tree lst)))
|
||||||
|
|
||||||
|
(define %set:delete-all
|
||||||
|
(lambda (tree lst)
|
||||||
|
(%set:operate-all (lambda (tree key _)
|
||||||
|
(smap:delete tree key)) tree lst)))
|
||||||
|
|
||||||
(define %set:tests
|
(define %set:tests
|
||||||
(list
|
(list
|
||||||
(cons "rotate right"
|
(cons "rotate right"
|
||||||
|
@ -354,4 +402,30 @@
|
||||||
((not (cdr delete-return)) "string not found")
|
((not (cdr delete-return)) "string not found")
|
||||||
((not (eqv? (car delete-return) '()))
|
((not (eqv? (car delete-return) '()))
|
||||||
"returned tree not null")
|
"returned tree not null")
|
||||||
|
(else #t))))))))))))
|
||||||
|
(cons "insert a few unique then delete"
|
||||||
|
(lambda ()
|
||||||
|
(let ((to-insert (list
|
||||||
|
(list (string #\a #\b #\c) 1 #f)
|
||||||
|
(list (string #\a #\b #\d) 2 #f)
|
||||||
|
(list (string #\d #\e #\f) 3 #f)
|
||||||
|
(list (string #\1 #\2 #\3 #\a #\C) 4 #f))))
|
||||||
|
(display "insert all") (newline)
|
||||||
|
(let ((tree (%set:insert-all '() to-insert)))
|
||||||
|
(if (string? tree)
|
||||||
|
tree
|
||||||
|
(begin
|
||||||
|
(for-each (lambda (x)
|
||||||
|
(list-set! x 2 (list-ref x 1)))
|
||||||
|
to-insert)
|
||||||
|
(display "search all") (newline)
|
||||||
|
(let ((res (%set:search-all tree to-insert)))
|
||||||
|
(if (string? res)
|
||||||
|
res
|
||||||
|
(begin
|
||||||
|
(display "delete all") (newline)
|
||||||
|
(let ((tree (%set:delete-all tree to-insert)))
|
||||||
|
(cond
|
||||||
|
((string? tree) tree)
|
||||||
|
((not (null? tree)) "did not delete everything")
|
||||||
(else #t))))))))))))))
|
(else #t))))))))))))))
|
||||||
|
|
Loading…
Reference in New Issue