|
101 | 101 | ;; Balancing ;;
|
102 | 102 | ;;-----------;;
|
103 | 103 |
|
| 104 | +;; Balance: -2 |
| 105 | +;; Left Rotation |
| 106 | +;; a c |
| 107 | +;; / \ / \ |
| 108 | +;; b c a e |
| 109 | +;; / \ / \ / \ |
| 110 | +;; d e b d f g |
| 111 | +;; / \ |
| 112 | +;; f g |
| 113 | + |
| 114 | +;; Balance: 2 |
| 115 | +;; Right Rotation |
| 116 | +;; a b |
| 117 | +;; / \ / \ |
| 118 | +;; b c d a |
| 119 | +;; / \ / \ / \ |
| 120 | +;; d e f g e c |
| 121 | +;; / \ |
| 122 | +;; f g |
| 123 | + |
| 124 | +(defgeneric rotate (rope direction) |
| 125 | + (:method ((rope branch) (direction (eql :left))) |
| 126 | + (with-slots (left right) rope |
| 127 | + (concat-rope* |
| 128 | + (concat-rope* left (branch-left right)) |
| 129 | + (branch-right right)))) |
| 130 | + (:method ((rope branch) (direction (eql :right))) |
| 131 | + (with-slots (left right) rope |
| 132 | + (concat-rope* |
| 133 | + (branch-left left) |
| 134 | + (concat-rope* (branch-right left) right))))) |
| 135 | + |
| 136 | +(defmethod rotate :around (rope direction) |
| 137 | + (format t "rope: ~a, rotating: ~a~%" (write-rope rope nil) direction) |
| 138 | + (call-next-method)) |
| 139 | + |
| 140 | +(defgeneric balance-direction (rope) |
| 141 | + (:method ((rope leaf)) |
| 142 | + nil) |
| 143 | + (:method ((rope branch)) |
| 144 | + (with-slots (left right) rope |
| 145 | + (let ((balance (- (rope-depth left) (rope-depth right)))) |
| 146 | + (cond ((< 1 balance) :right) |
| 147 | + ((> -1 balance) :left) |
| 148 | + (t nil)))))) |
| 149 | + |
| 150 | +;; (defmethod balance :around (rope) |
| 151 | +;; (let ((bal (call-next-method))) |
| 152 | +;; (format t "rope: ~a, balance: ~a~%" (write-rope rope nil) bal) |
| 153 | +;; bal)) |
| 154 | + |
| 155 | +(defgeneric balance-rope (rope) |
| 156 | + (:method ((rope leaf)) |
| 157 | + rope) |
| 158 | + (:method ((rope branch)) |
| 159 | + (with-slots (left right) rope |
| 160 | + (let* ((left (if (balance-direction left) (balance-rope left) left)) |
| 161 | + (right (if (balance-direction right) (balance-rope right) right)) |
| 162 | + (rope (concat-rope* left right)) |
| 163 | + (balance (balance rope))) |
| 164 | + (cond ((< 1 balance) |
| 165 | + (rotate rope :right)) |
| 166 | + ((> -1 balance) |
| 167 | + (rotate rope :left)) |
| 168 | + (t |
| 169 | + rope)))))) |
| 170 | + |
| 171 | +;;---------;; |
| 172 | +;; Rebuild ;; |
| 173 | +;;---------;; |
| 174 | + |
104 | 175 | (defun normalize-leaves (leaves &optional carry)
|
105 | 176 | (let ((leaf (car leaves)))
|
106 | 177 | (cond ((and carry (null leaf))
|
|
115 | 186 | (t
|
116 | 187 | (cons leaf (normalize-leaves (cdr leaves)))))))
|
117 | 188 |
|
118 |
| -(defgeneric balancedp (rope) |
119 |
| - (:documentation "Check if a rope is a height-balanced tree.") |
120 |
| - (:method ((rope leaf)) |
121 |
| - t) |
122 |
| - (:method ((rope branch)) |
123 |
| - (with-slots (left right) rope |
124 |
| - (and (balancedp left) |
125 |
| - (balancedp right) |
126 |
| - (>= 2 (abs (- (rope-depth left) (rope-depth right)))))))) |
127 |
| - |
128 | 189 | (defun merge-leaves (leaves start end)
|
129 | 190 | (let ((range (- end start)))
|
130 | 191 | (case range
|
|
134 | 195 | (concat-rope (merge-leaves leaves start mid)
|
135 | 196 | (merge-leaves leaves mid end)))))))
|
136 | 197 |
|
137 |
| -(defun balance-rope (rope &optional forcep) |
| 198 | +(defun rebuild-rope (rope) |
138 | 199 | "Balance a rope by reconstructing it from the bottom up."
|
139 |
| - (if (and (balancedp rope) (not forcep)) |
140 |
| - rope |
141 |
| - (let ((leaves (normalize-leaves (collect-rope rope)))) |
142 |
| - (merge-leaves leaves 0 (length leaves))))) |
| 200 | + (let ((leaves (normalize-leaves (collect-rope rope)))) |
| 201 | + (merge-leaves leaves 0 (length leaves)))) |
143 | 202 |
|
144 | 203 | ;;--------;;
|
145 | 204 | ;; Insert ;;
|
146 | 205 | ;;--------;;
|
147 | 206 |
|
148 | 207 | (defgeneric prepend-rope (rope source)
|
149 | 208 | (:documentation "Return a new rope with a string or rope inserted at the beginning of a rope.")
|
150 |
| - (:method (rope (source string)) |
151 |
| - (concat-rope (make-rope source) rope)) |
152 | 209 | (:method (rope (source rope))
|
153 |
| - (concat-rope source rope))) |
| 210 | + (concat-rope source rope)) |
| 211 | + (:method (rope (source t)) |
| 212 | + (concat-rope (make-rope source) rope))) |
154 | 213 |
|
155 | 214 | (defgeneric append-rope (rope source)
|
156 | 215 | (:documentation "Return a new rope with a string or rope inserted at the end of a rope.")
|
157 |
| - (:method (rope (source string)) |
158 |
| - (concat-rope rope (make-rope source))) |
159 | 216 | (:method (rope (source rope))
|
160 |
| - (concat-rope rope source))) |
| 217 | + (concat-rope rope source)) |
| 218 | + (:method (rope (source t)) |
| 219 | + (concat-rope rope (make-rope source)))) |
161 | 220 |
|
162 | 221 | (defun insert-rope (rope index str)
|
163 | 222 | "Return a new rope with a string or rope inserted at the specified index of a rope."
|
|
192 | 251 | ;; Concat ;;
|
193 | 252 | ;;--------;;
|
194 | 253 |
|
| 254 | +(defun concat-rope* (left right) |
| 255 | + "Concatenates without balancing." |
| 256 | + (make-instance 'branch |
| 257 | + :length (+ (rope-length left) (rope-length right)) |
| 258 | + :depth (1+ (max (rope-depth left) (rope-depth right))) |
| 259 | + :left left |
| 260 | + :right right)) |
| 261 | + |
195 | 262 | (defun concat-rope (left right)
|
196 | 263 | "Returns a balanced concatenation of two ropes."
|
197 |
| - (balance-rope |
198 |
| - (make-instance 'branch |
199 |
| - :length (+ (rope-length left) (rope-length right)) |
200 |
| - :depth (1+ (max (rope-depth left) (rope-depth right))) |
201 |
| - :left left |
202 |
| - :right right))) |
| 264 | + (balance-rope (concat-rope* left right))) |
203 | 265 |
|
204 | 266 | ;;-------;;
|
205 | 267 | ;; Split ;;
|
|
218 | 280 | ((< index weight)
|
219 | 281 | (multiple-value-bind (ante post) (split-rope left index)
|
220 | 282 | (values (balance-rope ante)
|
221 |
| - (balance-rope (concat-rope post right))))) |
| 283 | + (concat-rope post right)))) |
222 | 284 | ((> index weight)
|
223 | 285 | (multiple-value-bind (ante post) (split-rope right (- index weight))
|
224 |
| - (values (balance-rope (concat-rope left ante)) |
| 286 | + (values (concat-rope left ante) |
225 | 287 | (balance-rope post)))))))))
|
226 | 288 |
|
227 | 289 | ;;------;;
|
|
0 commit comments