binary search algorithm made publicly usable
authorClaus Gittinger <cg@exept.de>
Sat, 17 Jan 2009 15:38:14 +0100
changeset 11478 0cdba0734b9f
parent 11477 2a46e08433d3
child 11479 d3eff0be6d48
binary search algorithm made publicly usable
SortedCollection.st
--- a/SortedCollection.st	Sat Jan 17 11:39:27 2009 +0100
+++ b/SortedCollection.st	Sat Jan 17 15:38:14 2009 +0100
@@ -324,6 +324,96 @@
     ^ self withAll:aCollection sortBlock:aBlock
 ! !
 
+!SortedCollection class methodsFor:'helpers'!
+
+binarySearch:aSortedArray for:anObject
+    "search for an existing element; return true if found.
+     by checking if the element at the returned index is the one we look for.
+     Uses a binarySearch since we can depend on the elements being on sorted order.
+     The returned index is a physical one, for accessing contentsArray.
+     This is only to be used for arrays which are known to be sorted."
+
+    |idx|
+
+    idx := self
+        binarySearch:aSortedArray 
+        forIndexOf:anObject.
+    ^ idx <= aSortedArray size
+    and:[ (aSortedArray at:idx) = anObject ].
+
+    "
+     SortedCollection
+        binarySearch:#(1 2 3 4 7 99 1313 981989 898989898) 
+        for:898989898    
+    "
+!
+
+binarySearch:aSortedArray forIndexOf:anObject
+    "search the index at which to insert anObject.
+     Can also be used to search for an existing element
+     by checking if the element at the returned index is the one we look for.
+     Uses a binarySearch since we can depend on the elements being on sorted order.
+     The returned index is a physical one, for accessing contentsArray.
+     This is only to be used for arrays which are known to be sorted."
+
+    ^ self
+        binarySearch:aSortedArray 
+        from:1 to:(aSortedArray size)
+        forIndexOf:anObject 
+        usingSortBlock:[:a :b | a < b ]
+
+    "
+     SortedCollection
+        binarySearch:#(1 2 3 4 7 99 1313 981989 898989898) 
+        from:1 to:9
+        forIndexOf:99
+        usingSortBlock:[:a :b | a < b ]
+    "
+
+    "Modified: 12.4.1996 / 13:22:03 / cg"
+!
+
+binarySearch:aSortedArray from:firstIndex to:lastIndex forIndexOf:anObject usingSortBlock:sortBlock
+    "search the index at which to insert anObject.
+     Can also be used to search for an existing element
+     by checking if the element at the returned index is the one we look for.
+     Uses a binarySearch since we can depend on the elements being on sorted order.
+     The returned index is a physical one, for accessing contentsArray.
+     This is only to be used for arrays which are known to be sorted."
+
+    |low    "{ Class: SmallInteger}"
+     high   "{ Class: SmallInteger}"
+     middle "{ Class: SmallInteger}"
+     element|
+
+    "
+     we can of course use a binary search - since the elements are sorted
+    "
+    low := firstIndex.
+    high := lastIndex.
+    [low > high] whileFalse:[
+        middle := (low + high) // 2.
+        element := aSortedArray at:middle.
+        (sortBlock value:element value:anObject) ifTrue:[
+            "middleelement is smaller than object"
+            low := middle + 1
+        ] ifFalse:[
+            high := middle - 1
+        ]
+    ].
+    ^ low
+
+    "
+     SortedCollection
+        binarySearch:#(1 2 3 4 7 99 1313 981989 898989898) 
+        from:1 to:9
+        forIndexOf:99
+        usingSortBlock:[:a :b | a < b ]
+    "
+
+    "Modified: 12.4.1996 / 13:22:03 / cg"
+! !
+
 !SortedCollection methodsFor:'accessing'!
 
 largest:n
@@ -767,31 +857,16 @@
      Uses a binarySearch since we can depend on the elements being on sorted order.
      The returned index is a physical one, for accessing contentsArray."
 
-    |low    "{ Class: SmallInteger}"
-     high   "{ Class: SmallInteger}"
-     middle "{ Class: SmallInteger}"
-     element|
-
-    "
-     we can of course use a binary search - since the elements are sorted
-    "
-    low := firstIndex.
-    high := lastIndex.
-    [low > high] whileFalse:[
-        middle := (low + high) // 2.
-        element := contentsArray at:middle.
-        (sortBlock value:element value:anObject) ifTrue:[
-            "middleelement is smaller than object"
-            low := middle + 1
-        ] ifFalse:[
-            high := middle - 1
-        ]
-    ].
-    ^ low
+    ^ self class
+        binarySearch:contentsArray 
+        from:firstIndex to:lastIndex 
+        forIndexOf:anObject usingSortBlock:sortBlock
 
     "
      #(1 2 3 4 7 99 1313 981989 898989898) asSortedCollection indexForInserting:50
+
      #(1.0 2.0 3 4 7 49.0 51.0 99 1313 981989 898989898) asSortedCollection indexForInserting:50
+
     "
 
     "Modified: 12.4.1996 / 13:22:03 / cg"
@@ -995,7 +1070,7 @@
 !SortedCollection class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libbasic/SortedCollection.st,v 1.66 2008-10-24 15:04:29 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/SortedCollection.st,v 1.67 2009-01-17 14:38:14 cg Exp $'
 ! !
 
 SortedCollection initialize!