zoukankan      html  css  js  c++  java
  • scheme 学习:红黑树

    这几天继续学习scheme,scheme中虽然有hashtable但没有类似C++中的map,于是把C版本中的红黑树移植到scheme(中间也发现了C版本中的一些问题,暂时懒得调整了^()^)

    以作为后序set和表格驱动设计中表格的基础数据结构.

    虽说这个红黑树在C版本中是调试好的了,但移植过来还是花费了我一天多的时间,中间出现各种小问题,苦于并不熟悉如何调试scheme程序,所以进度十分缓慢.

    (注:代码中大量使用set-car!所以无法再racket中运行,当然也可以调整rbnode的表示形式,不使用list来表示各字段,只使用set!修改字段的内容以使得可以被

    racket支持)

    (begin
        (define nil-node (list 0 0 'black '() '() '()))
        ;红黑树节点的定义
        ;节点结构如下
        ;(key (val (color (parent (left (right nil))))))
        
        (define (make-rb-node key val)
            (list key val 'red '() '() '())
        )
            
        (define (get-key rbnode)
            (car rbnode))
        
        (define (get-val rbnode)
            (cadr rbnode))
        
        (define (set-val! rbnode val)
            (set-car! (cdr rbnode) val))
        
        (define (get-color rbnode)
            (caddr rbnode))
        
        (define (set-color! rbnode color)
            (set-car! (cddr rbnode) color))
            
        (define (get-parent rbnode)
            (cadddr rbnode))    
        
        (define (set-parent! rbnode parent)
            (if (not (equal? rbnode nil-node))
            (set-car! (cdddr rbnode) parent)))
            
        (define (get-left rbnode)
            (car (cddddr rbnode)))
        
        (define (set-left! rbnode left)
            (if (not (equal? rbnode nil-node))
            (set-car! (cddddr rbnode) left)))
            
        (define (get-right rbnode)
            (cadr (cddddr rbnode)))
            
        (define (set-right! rbnode right)
            (if (not (equal? rbnode nil-node))
            (set-car! (cdr (cddddr rbnode)) right)))
        
        (define (color-flip rbnode)
            (if (and (not (null? (get-left rbnode)))
                     (not (null? (get-right rbnode))))
                (begin (set-color! rbnode 'red)
                       (set-color! (get-left rbnode) 'black)
                       (set-color! (get-right rbnode) 'black)
                        #t)
            #f)            
        )
        
        
        ;红黑树定义
        ;(root (size nil))
        (define (make-rbtree comp-function)
            ;(let ((rbtree (list nil 0 nil)))
            (let ((root nil-node)(size 0)(cmp-function comp-function))
            
            (define (rbtree-get-root) root)
            
            (define (rbtree-set-root! new-root) (set! root new-root))
            
            (define (rbtree-get-size) size)
                        
            (define (rbtree-insert key val)
                (define rbnode (make-rb-node key val))
                (define child_link '())
                (define parent nil-node)
                (define cmp cmp-function)
                (define (iter cur)
                    (if (equal? cur nil-node) #t
                        (begin
                            (set! parent cur)
                            (let ((ret (cmp key (get-key cur))))
                            (cond ((= 0 ret) #f)
                                  (else (if (< ret 0) (begin (set! child_link (cddddr cur))
                                                             (set! cur (get-left cur)))
                                                      (begin (set! child_link (cdr (cddddr cur)))
                                                             (set! cur (get-right cur))))         
                                        (iter cur))))
                        )))
                (if (not (iter (rbtree-get-root))) #f
                    (begin
                        (set-left! rbnode nil-node)
                        (set-right! rbnode nil-node)
                        (set-parent! rbnode parent)
                        (if (not (null? child_link)) (set-car! child_link rbnode))
                        (set! size (+ 1 size))
                        (if (= 1 size)(rbtree-set-root! rbnode))
                        (insert-fix-up rbnode)
                        #t
                    ))
            )
            
            (define (rbtree-find-imp key)
                (define (iter node)
                    (define cmp cmp-function)
                    (if (equal? node nil-node)'()
                        (let ((ret (cmp key (get-key node))))
                            (cond ((= 0 ret) node)
                                  ((= -1 ret) (iter (get-left node)))
                                  (else (iter (get-right node)))))))
                (if (= 0 size) '()
                    (iter root))
            )
            
            (define (rbtree-find key)
                (define ret (rbtree-find-imp key))
                (if (null? ret) ret (get-val ret))
            )
            
            (define (rbtree-remove key)
                (define rbnode (rbtree-find-imp key))
                (if (null? rbnode)'()
                    (rbtree-delete rbnode))
                rbnode    
            )
            
            ;获取用于代替将被删除节点的节点
            (define (get-replace-node rbnode)
                (cond ((and (equal? (get-left rbnode) nil-node)
                            (equal? (get-right rbnode) nil-node))rbnode)
                      ((not (equal? (get-right rbnode) nil-node)) (minimum (get-right rbnode)))        
                      (else (maxmum (get-left rbnode))))
            )
            
            (define (rbtree-delete rbnode)
                (define x (get-replace-node rbnode));用x替代rbnode的位置
                (define rb-parent (get-parent rbnode));rbnode的父亲
                (define x-parent (get-parent x));x的父亲
                (define x-old-color (get-color x))
                (define fix-node nil-node)
                (if (equal? nil-node (get-left x))(set! fix-node (get-right x))
                    (set! fix-node (get-left x)))
                (if (not (equal? x rbnode));如果x与rbnode不是同一个节点
                    (begin
                        ;x的父亲不是rbnode,将x的孩子交给它的父亲
                        (if (not (equal? x-parent rbnode))
                            (let ((child (if (not (equal? nil-node (get-left x)))(get-left x)
                                             (get-right x))))
                                 (set-parent! child x-parent)             
                                 (if (equal? x (get-left x-parent)) 
                                     (set-left! x-parent child)    
                                     (set-right! x-parent child))))
                        
                        (if (not (equal? nil-node rb-parent))
                            ;如果rb-parent不为nil让x成为rb-parent的孩子    
                            (begin
                                (if (equal? rbnode (get-left rb-parent))(set-left! rb-parent x)
                                    (set-right! rb-parent x))
                                (set-parent! x rb-parent)    
                            )
                            ;否则将x父亲设为nil
                            (set-parent! x nil-node))
                        ;将rbnode的孩子移交给x
                        (let ((rb-left (get-left rbnode))(rb-right (get-right rbnode)))
                            (if (not (equal? nil-node rb-left))
                                (begin (set-left! x rb-left)(set-parent! rb-left x)))
                            (if (not (equal? nil-node rb-right))
                                (begin (set-right! x rb-right)(set-parent! rb-right x))))                        
                    ))
                ;将rbnode的所有关系清除    
                (set-left! rbnode nil-node)(set-right! rbnode nil-node)(set-parent! rbnode nil-node)
                (if (equal? root rbnode)
                            (rbtree-set-root! x))
                (set! size (- size 1))    
                (if (and (equal? nil-node fix-node) (eq? x-old-color 'black))
                    (delete-fix-up fix-node))        
            )
                
            (define (rotate-left rbnode)
                (define parent (get-parent rbnode))
                (define right (get-right rbnode))
                (if (not (equal? nil-node right))
                    (begin
                        (set-right! rbnode (get-left right))
                        (set-parent! (get-left right) rbnode)
                        (if (equal? root rbnode) (rbtree-set-root! right)
                            (begin
                                (if (equal? rbnode (get-left parent))(set-left! parent right)
                                    (set-right! parent right))))
                        (set-parent! right parent)
                        (set-parent! rbnode right)
                        (set-left! right rbnode)
                    #t)
                #f)
            )
            
            (define (rotate-right rbnode)
                (define parent (get-parent rbnode))
                (define left (get-left rbnode))
                (if (not (equal? nil-node left))
                    (begin
                        (set-left! rbnode (get-right left))
                        (set-parent! (get-right left) rbnode)
                        (if (equal? root rbnode) (rbtree-set-root! left)
                            (begin
                                (if (equal? rbnode (get-left parent))(set-left! parent left)
                                    (set-right! parent left))))
                        (set-parent! left parent)
                        (set-parent! rbnode left)
                        (set-right! left rbnode)
                    #t)
                #f)
            )
            
            (define (insert-fix-up rbnode)
                (define (iter n)
                    (if (eq? (get-color (get-parent n)) 'black)
                        (set-color! root 'black)
                        (begin
                            (let ((parent (get-parent n))(grand_parent (get-parent (get-parent n))))
                            (if (equal? parent (get-left grand_parent))
                                (begin
                                    (let ((ancle (get-right grand_parent)))
                                    (if (eq? (get-color ancle) 'red)
                                        (begin (color-flip grand_parent) (set! n grand_parent))
                                        (begin 
                                            (if (equal? n (get-right parent))
                                                (begin (set! n parent)(rotate-left n)))
                                         (set-color! (get-parent n) 'black)
                                         (set-color! (get-parent (get-parent n)) 'red)
                                         (rotate-right (get-parent (get-parent n))))))        
                                )
                                (begin
                                    (let ((ancle (get-left grand_parent)))
                                    (if (eq? (get-color ancle) 'red)
                                        (begin (color-flip grand_parent) (set! n grand_parent))
                                        (begin 
                                            (if (equal? n (get-left parent))
                                                (begin (set! n parent)(rotate-right n)))
                                         (set-color! (get-parent n) 'black)
                                         (set-color! (get-parent (get-parent n)) 'red)
                                         (rotate-left (get-parent (get-parent n))))))                            
                                )))
                             (iter n))))
                (iter rbnode)
            )
    
            (define (delete-fix-up rbnode)
                (define (iter n)
                    (if (not (and (not (equal? n root))
                                  (not (equal? (get-color n) 'red))))
                        (set-color! n 'black)
                        (begin
                            (let ((parent (get-parent n)))
                            (if (equal? n (get-left parent))
                                (begin
                                    (let ((w (get-right parent)))
                                    (if (eq? 'red (get-color w))
                                        (begin
                                            (set-color! w 'black)
                                            (set-color! parent 'red)
                                            (rotate-left parent)
                                            (set! w (get-right parent))))
                                    (if (and (eq? 'black (get-color (get-left w)))
                                             (eq? 'black (get-color (get-right w))))
                                        (begin (set-color! w 'red)(set! n parent))
                                        (begin
                                            (if (eq? (get-color (get-right w)) 'black)
                                                (begin
                                                    (set-color! (get-left w) 'black)
                                                    (set-color! w 'red)
                                                    (rotate-right w)
                                                    (set! w (get-right parent))
                                                ))
                                            (set-color! w (get-color parent))
                                            (set-color! parent 'black)
                                            (set-color! (get-right w) 'black)
                                            (rotate-left parent)
                                            (set! n root)    
                                        ))))
                                (begin
                                    (let ((w (get-left parent)))
                                    (if (eq? 'red (get-color w))
                                        (begin
                                            (set-color! w 'black)
                                            (set-color! parent 'red)
                                            (rotate-right parent)
                                            (set! w (get-left parent))))
                                    (if (and (eq? 'black (get-color (get-left w)))
                                             (eq? 'black (get-color (get-right w))))
                                        (begin (set-color! w 'red)(set! n parent))
                                        (begin
                                            (if (eq? (get-color (get-left w)) 'black)
                                                (begin
                                                    (set-color! (get-right w) 'black)
                                                    (set-color! w 'red)
                                                    (rotate-left w)
                                                    (set! w (get-left parent))
                                                ))
                                            (set-color! w (get-color parent))
                                            (set-color! parent 'black)
                                            (set-color! (get-left w) 'black)
                                            (rotate-right parent)
                                            (set! n root)    
                                        ))))))                    
                            (iter n))))
                (iter rbnode)
            )
            
            (define (minimum rbnode)
                (define (minimum-imp rbnode)
                    (if (equal? (get-left rbnode) nil-node)
                        rbnode
                        (minimum-imp (get-left rbnode))))
                (minimum-imp rbnode))
                
            (define (maxmum rbnode)
                (define (maxmum-imp rbnode)
                    (if (equal? (get-right rbnode) nil-node)
                        rbnode
                        (maxmum-imp (get-right rbnode))))
                (maxmum-imp rbnode))        
                    
            (define (successor rbnode)
                (define (iter parent node)
                    (if (and (not (equal? parent nil-node))
                             (equal? (get-right parent) node))
                        (iter (get-parent parent) parent)
                        parent))
                (if (not (equal? (get-right rbnode) nil-node))
                    (minimum (get-right rbnode))
                    (iter (get-parent rbnode) rbnode)))    
                    
            (define (node-next rbnode)
                (display (get-key rbnode))(newline)
                (if (null? rbnode) '()
                    (begin
                        (let ((succ (successor rbnode)))
                            (if (equal? succ nil-node) '() succ))
                    )))    
                    
            (define (rbtree->array)
                (define (iter rbnode ret)
                    (if (null? rbnode) ret
                        (iter (node-next rbnode) (cons (get-val rbnode) ret)))
                )
                (iter (minimum root) '())
            )                
            
            (lambda (op . arg)
            (cond ((eq? op 'find) (rbtree-find  (car arg)))
                  ((eq? op 'remove) (rbtree-remove  (car arg)))
                  ((eq? op 'insert) (rbtree-insert (car arg) (cadr arg)))
                  ((eq? op 'size) size)
                  ((eq? op 'root) (get-key root))
                  ((eq? op 'tree->array-desc) (rbtree->array))
                  ((eq? op 'tree->array-asc) (reverse (rbtree->array)))
                  (else "bad op")))
        ))
    
        (define (default-cmp a b)
            (cond ((= a b) 0)
                  ((< a b) -1)
                  (else 1)))
                  
        (define r (make-rbtree default-cmp))
    
        (r 'insert 1 1)
        (r 'insert 4 4)
        (r 'insert 5 5)
        (r 'insert 11 11)
        (r 'insert 15 15)
        (r 'insert 8 8)
        (r 'insert 2 2)
        (r 'insert 3 3)
        (r 'insert 6 6)
        (r 'insert 7 7)    
    
    )
  • 相关阅读:
    清除所有标签的属性
    chm提取
    视频分享
    依赖注入
    python-markdown
    light sdk
    ~
    html标签引入外部html
    微信公众平台自定义菜单
    还在为需要ajax而导入jquery吗? 纯js封装ajax操作
  • 原文地址:https://www.cnblogs.com/sniperHW/p/3110146.html
Copyright © 2011-2022 走看看