(defpackage :bintree (:use :cl ) (:export )) (in-package :bintree) (defclass bintree () ((value :initarg :value :accessor node-value) (%left :initarg :left :accessor tree-left :initform nil) (%right :initarg :right :accessor tree-right :initform nil))) (define-condition constraint-violated (serious-condition) ()) (defmethod (setf tree-left) :before ((new-value bintree) (object bintree)) (unless (<= (node-value new-value) (node-value object)) (error 'constraint-violated))) (defmethod (setf tree-left) ((new-value integer) (object bintree)) (setf (tree-left object) (make-instance 'bintree :value new-value))) (defmethod (setf tree-right) :before ((new-value bintree) (object bintree)) (unless (> (node-value new-value) (node-value object)) (error 'constraint-violated))) (defmethod (setf tree-right) ((new-value integer) (object bintree)) (setf (tree-right object) (make-instance 'bintree :value new-value))) (defun insert (tree value) (if (<= value (node-value tree)) (if (null (tree-left tree)) (setf (tree-left tree) value) (insert (tree-left tree) value)) (if (null (tree-right tree)) (setf (tree-right tree) value) (insert (tree-right tree) value)))) (defun rotate (tree direction) (ecase direction (:right (let* ((right-child (tree-right tree)) (left-of-right (tree-left right-child))) (setf (tree-left right-child) tree (tree-right tree) left-of-right) right-child)) (:left (let* ((left-child (tree-left tree)) (right-of-left (tree-right left-child))) (setf (tree-right left-child) tree (tree-left tree) right-of-left) left-child)))) (defun list->tree (list) (declare (optimize (debug 3))) (destructuring-bind (root . rest) list (let ((result (make-instance 'bintree :value root))) (mapcar (lambda (v) (insert result v)) rest) result))) (defmethod print-object ((object bintree) stream) (labels ((print-node (node stream) (if node (format stream "~a (~a) (~a)" (node-value node) (print-node (tree-left node) nil) (print-node (tree-right node) nil)) (format stream "~a" node)))) (print-unreadable-object (object stream :type t :identity t) (format stream "(~a)" (print-node object nil)))))