#lang s-exp "lang.ss"
(define-struct rbtree (color key value lkid rkid))
(define empty-rbtree
(make-rbtree 'black 'nil 'nil 'nil 'nil))
(define (rbtree-empty? t)
(eq? t empty-rbtree))
(define (rbtree-color-red? c)
(eq? c 'red))
(define (rbtree-color-black? c)
(eq? c 'black))
(define (rbtree-lookup lt? t k)
(cond [(rbtree-empty? t)
#f]
[(lt? k (rbtree-key t))
(rbtree-lookup lt? (rbtree-lkid t) k)]
[(lt? (rbtree-key t) k)
(rbtree-lookup lt? (rbtree-rkid t) k)]
[else
(list (rbtree-key t) (rbtree-value t))]))
(define (rbtree-insert lt? t k v)
(local [(define (ins t)
(cond [(rbtree-empty? t) (make-rbtree 'red k v empty-rbtree empty-rbtree)]
[(lt? k (rbtree-key t))
(rbtree-balance (rbtree-color t) (rbtree-key t) (rbtree-value t) (ins (rbtree-lkid t)) (rbtree-rkid t))]
[(lt? (rbtree-key t) k)
(rbtree-balance (rbtree-color t) (rbtree-key t) (rbtree-value t) (rbtree-lkid t) (ins (rbtree-rkid t)))]
[else
(make-rbtree (rbtree-color t) k v (rbtree-lkid t) (rbtree-rkid t))]))]
(let ([z (ins t)])
(make-rbtree 'black (rbtree-key z) (rbtree-value z) (rbtree-lkid z) (rbtree-rkid z)))))
(define (rbtree-balance c k v l r)
(cond [(and (rbtree-color-black? c) (rbtree-color-red? (rbtree-color l)) (rbtree-color-red? (rbtree-color (rbtree-lkid l))))
(make-rbtree 'red (rbtree-key l) (rbtree-value l)
(make-rbtree 'black (rbtree-key (rbtree-lkid l)) (rbtree-value (rbtree-lkid l))
(rbtree-lkid (rbtree-lkid l)) (rbtree-rkid (rbtree-lkid l)))
(make-rbtree 'black k v (rbtree-rkid l) r))]
[(and (rbtree-color-black? c) (rbtree-color-red? (rbtree-color l)) (rbtree-color-red? (rbtree-color (rbtree-rkid l))))
(make-rbtree 'red (rbtree-key (rbtree-rkid l)) (rbtree-value (rbtree-rkid l))
(make-rbtree 'black (rbtree-key l) (rbtree-value l) (rbtree-lkid l) (rbtree-lkid (rbtree-rkid l)))
(make-rbtree 'black k v (rbtree-rkid (rbtree-rkid l)) r))]
[(and (rbtree-color-black? c) (rbtree-color-red? (rbtree-color r)) (rbtree-color-red? (rbtree-color (rbtree-lkid r))))
(make-rbtree 'red (rbtree-key (rbtree-lkid r)) (rbtree-value (rbtree-lkid r))
(make-rbtree 'black k v l (rbtree-lkid (rbtree-lkid r)))
(make-rbtree 'black (rbtree-key r) (rbtree-value r) (rbtree-rkid (rbtree-lkid r)) (rbtree-rkid r)))]
[(and (rbtree-color-black? c) (rbtree-color-red? (rbtree-color r)) (rbtree-color-red? (rbtree-color (rbtree-rkid r))))
(make-rbtree 'red (rbtree-key r) (rbtree-value r)
(make-rbtree 'black k v l (rbtree-lkid r))
(make-rbtree 'black (rbtree-key (rbtree-rkid r)) (rbtree-value (rbtree-rkid r))
(rbtree-lkid (rbtree-rkid r)) (rbtree-rkid (rbtree-rkid r))))]
[else (make-rbtree c k v l r)]))
(define (rbtree->list t)
(local [(define (enlist t xs)
(cond [(rbtree-empty? t) xs]
[(and (rbtree-empty? (rbtree-lkid t)) (rbtree-empty? (rbtree-rkid t)))
(cons (list (rbtree-key t) (rbtree-value t)) xs)]
[else (enlist (rbtree-lkid t)
(cons (list (rbtree-key t) (rbtree-value t))
(enlist (rbtree-rkid t) xs)))]))]
(enlist t empty)))
(provide/contract [empty-rbtree
rbtree?]
[rbtree-insert
((any/c any/c . -> . boolean?) rbtree? any/c any/c
. -> . rbtree?)]
[rbtree-lookup
((any/c any/c . -> . boolean?) rbtree? any/c
. -> . (or/c false/c (list/c any/c any/c)))]
[rbtree->list
(rbtree? . -> . (listof (list/c any/c any/c)))])