[funds-cvs] r47 - trunk/funds/src/trees

abaine at common-lisp.net abaine at common-lisp.net
Tue Jul 3 20:18:23 UTC 2007


Author: abaine
Date: Tue Jul  3 16:18:23 2007
New Revision: 47

Modified:
   trunk/funds/src/trees/avl-tree.lisp
Log:
Refactored left and right-insert out of program.

Modified: trunk/funds/src/trees/avl-tree.lisp
==============================================================================
--- trunk/funds/src/trees/avl-tree.lisp	(original)
+++ trunk/funds/src/trees/avl-tree.lisp	Tue Jul  3 16:18:23 2007
@@ -3,7 +3,6 @@
 
 ;;;; Public Interface
 
-
 (defun empty-avl-tree ()
   "An empty AVL Tree."
   nil)
@@ -30,8 +29,12 @@
 						      :value value
 						      :left (avl-left tree)
 						      :right (avl-right tree)))
-	((funcall order key (avl-key tree)) (left-insert tree key value test order))
-	(t (right-insert tree key value test order))))
+; ((funcall order key (avl-key tree)) (left-insert tree key value test order))
+; (t (right-insert tree key value test order))
+	(t (funcall (if (funcall order key (avl-key tree))
+			#'left-insert
+			#'right-insert)
+		    tree key value test order))))
 
 (defun avl-find-value (tree key &key (order #'<) (test #'eql))
   "The value associated with the given key in the given AVL Tree.  The function
@@ -63,44 +66,90 @@
   "The AVL tree that results when the given key-value pair is inserted
 into left sub-tree of the given AVL tree.  Only non-empty avl-trees 
 should be supplied as arguments."
-  (let ((left (avl-insert (avl-left tree) key value :test test :order order))
-	(right (avl-right tree)))
-    (if (imbalanced left right)
-	(if (left-heavy left)
-	    (right-rotate right tree left)
-	    (right-rotate right
-			  tree 
-			  (left-rotate (avl-left left)
-				       left
-				       (avl-right left))))
-	(make-avl :ht (parent-height left right)
-		  :key (avl-key tree)
-		  :value (avl-value tree)
-		  :left left
-		  :right right))))
+;;   (let ((left (avl-insert (avl-left tree) key value :test test :order order))
+;; 	(right (avl-right tree)))
+;;     (if (imbalanced left right)
+;; 	(if (left-heavy left)
+;; 	    (right-rotate right tree left)
+;; 	    (right-rotate right
+;; 			  tree 
+;; 			  (left-rotate (avl-left left)
+;; 				       left
+;; 				       (avl-right left))))
+;; 	(make-avl :ht (parent-height left right)
+;; 		  :key (avl-key tree)
+;; 		  :value (avl-value tree)
+;; 		  :left left
+;; :right right)))
+  (side-insert tree key value test order :side :left))
 
 (defun right-insert (tree key value test order)
   "The AVL tree that results when the given key-value pair is inserted
 into the right sub-tree of the given AVL tree.  Only non-empty avl-trees
 should be supplied as the tree argument."
-  (let ((right (avl-insert (avl-right tree) key value :test test :order order))
-	(left (avl-left tree)))
-    (if (imbalanced left right)
-	(if (right-heavy right)
-	    (left-rotate left tree right)
-	    (left-rotate left
-			 tree
-			 (right-rotate (avl-right right)
-				       right
-				       (avl-left right))))
-	(make-avl :ht (parent-height left right)
-		  :key (avl-key tree)
-		  :value (avl-value tree)
-		  :left left
-		  :right right))))
+;;   (let ((right (avl-insert (avl-right tree) key value :test test :order order))
+;; 	(left (avl-left tree)))
+;;     (if (imbalanced left right)
+;; 	(if (right-heavy right)
+;; 	    (left-rotate left tree right)
+;; 	    (left-rotate left
+;; 			 tree
+;; 			 (right-rotate (avl-right right)
+;; 				       right
+;; 				       (avl-left right))))
+;; 	(make-avl :ht (parent-height left right)
+;; 		  :key (avl-key tree)
+;; 		  :value (avl-value tree)
+;; 		  :left left
+;; 		  :right right)))
+  (side-insert tree key value test order :side :right)
+)
+
+(defun side-insert (tree key value test order &key side)
+  (let ((out (avl-insert (funcall (side-accessor side) tree) key value :test test :order order))
+	(in (funcall (other-side-accessor side) tree)))
+    (if (balanced out in) 
+	(make-avl :ht (parent-height out in)
+				    :key (avl-key tree)
+				    :value (avl-value tree)
+				    side out
+				    (other-side side) in)
+	(funcall (other-side-rotator side) 
+		 in 
+		 tree
+		 (if (funcall (side-heavy-predicate side) out)
+		     out
+		     (funcall (side-rotator side)
+			      (funcall (side-accessor side) out)
+			      out
+			      (funcall (other-side-accessor side) out)))))))
+
+
 
 ;;;; Rotation Functions
 
+(defun left-p (side)
+  (eq side :left))
+
+(defun other-side (side)
+  (if (left-p side) :right :left))
+
+(defun side-accessor (side)
+  (if (left-p side) #'avl-left #'avl-right))
+
+(defun other-side-accessor (side)
+  (side-accessor (other-side side)))
+
+(defun side-rotator (side)
+  (if (left-p side) #'left-rotate #'right-rotate))
+
+(defun other-side-rotator (side)
+  (side-rotator (other-side side)))
+
+(defun side-heavy-predicate (side)
+  (if (left-p side) #'left-heavy #'right-heavy))
+
+
 (defun left-rotate (t0 a b)
   (rotate t0 a b :direction :left))
 
@@ -108,11 +157,10 @@
   (rotate t3 c b :direction :right))
 
 (defun rotate (inside root outside &key direction)
-  (let* ((left-p (eq direction :left))
-	 (outside-accessor (if left-p #'avl-right #'avl-left))
-	 (inside-accessor (if left-p #'avl-left #'avl-right))
-	 (inside-init-key (if left-p :left :right))
-	 (outside-init-key (if left-p :right :left))
+  (let* ((outside-accessor (other-side-accessor direction))
+	 (inside-accessor (side-accessor direction))
+	 (inside-init-key direction)
+	 (outside-init-key (other-side direction))
 	 (new-outside (funcall outside-accessor outside))
 	 (new-inside (make-avl :ht (1- (avl-height root))
 			       :key (avl-key root)
@@ -127,6 +175,9 @@
 
 ;;;; AVL Tree utility functions
 
+(defun avl-balanced-p (tree)
+  (< -2 (balance-factor tree) 2))
+
 (defun imbalanced (left right)
   "Whether the heights of the given sub-trees differ,
 in their absolute values, by more than one."



More information about the Funds-cvs mailing list