Advertisement
waf9000

Doubly Linked Lists

Dec 20th, 2017
127
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Racket 3.28 KB | None | 0 0
  1. #lang racket
  2.  
  3. (provide empty-dlink dlink? view-dlink -> <- dl-cons )
  4.  
  5. (struct node (l k r) #:transparent)
  6. (struct head (n))
  7. (struct tail (n))
  8.  
  9. ;; An empty dlink, initialized to point at the tail
  10. (define empty-dlink
  11.   (tail (head #f)))
  12.  
  13. (define (dlink? p)
  14.  
  15.   ;; This helper traverses in the direction dir and ensures that the tree is left/right linear, and null terminated correctly.
  16.   (define (linear? n [dir node-l])
  17.  
  18.    
  19.     (let {;; empty-dir is the direction opposite to dir. It should be empty, if this is a correct dlinked list.
  20.           [empty-dir (cadr (member dir `(,node-l ,node-r ,node-l)))]
  21.  
  22.           ;; This is the corresponding null terminator for the dir.
  23.           [null-ptr? (cadr (member dir (list node-l (conjoin head? (negate head-n))
  24.                                              node-r (conjoin tail? (negate tail-n)))))]}
  25.  
  26.       ;; Either this node is a null terminator, or there's more to traverse
  27.       (or (null-ptr? n)
  28.           (and (node? n)
  29.                (empty? (empty-dir n))
  30.                (linear? (dir n) dir)))))
  31.  
  32.   ;; The cases
  33.   (or (and (node? p)
  34.            (linear? (node-l p) node-l)
  35.            (linear? (node-r p) node-r))
  36.       (and (head? p)
  37.            (linear? (head-n p) node-r))
  38.       (and (tail? p)
  39.            (linear? (tail-n p) node-l))))
  40.  
  41. (define (view-dlink p)
  42.   ;; This helper traverses in the direction dir and ensures that the tree is left/right linear, and null terminated correctly.
  43.   (define (linear n [dir node-l])
  44.  
  45.    
  46.     (let {;; empty-dir is the direction opposite to dir. It should be empty, if this is a correct dlinked list.
  47.           [empty-dir (cadr (member dir `(,node-l ,node-r ,node-l)))]
  48.  
  49.           ;; This is the corresponding null terminator for the dir.
  50.           [null-ptr? (cadr (member dir (list node-l (conjoin head? (negate head-n))
  51.                                              node-r (conjoin tail? (negate tail-n)))))]}
  52.  
  53.       ;; Either this node is a null terminator, or there's more to traverse
  54.       (cond
  55.         [(null-ptr? n) `(,n)]
  56.         [(and (node? n) (empty? (empty-dir n))) (cons (node-k n) (linear (dir n) dir))]
  57.         [else (printf "got ~a, ~a\n" n dir)])))
  58.   (match p
  59.     [(head n) `(head ,(linear n node-r))]
  60.     [(tail n) `(,(reverse (linear n node-l)) tail)]
  61.     [(node l k r) `(,(reverse (linear l node-l)) (root ,k) ,(linear r node-r))]))
  62.  
  63. (define (-> n)
  64.   (match n    
  65.     ;; rotate the head
  66.     [(head (tail #f))      (tail (head #f))]
  67.     [(head (node '() k r)) (node (head #f) k r)]
  68.    
  69.     ;; if the right is a tail, return the tail
  70.     [(node l k (tail #f)) (tail (node l k '()))]
  71.    
  72.     ;; else, do some rotating
  73.     [(node l b (node '() c r)) (node (node l b '()) c r)]))
  74.  
  75. (define (<- n)
  76.   (match n
  77.     ;; rotate the tail
  78.     [(tail (head #f))          (head (tail #f))]
  79.     [(tail (node l k '())) (node l k (tail #f))]
  80.  
  81.     ;; if the left is a head, return the head
  82.     [(node (head #f) k r) (head (node '() k r))]
  83.  
  84.     ;; else, do some rotating
  85.     [(node (node l a '()) b r) (node l a (node '() b r))]))
  86.  
  87. ;; Adds a node in front of the current node, also moves the pointer (so it feels a lot like the built-in cons)
  88. (define (dl-cons e dl)
  89.   (match dl
  90.     [(tail n) (node n e (tail #f))]
  91.     [(node l k r) (node l e (node '() k r))]))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement