]> granicus.if.org Git - icu/commitdiff
ICU-10081 uprv_stableBinarySearch() internal API
authorMarkus Scherer <markus.icu@gmail.com>
Sat, 4 May 2013 18:58:23 +0000 (18:58 +0000)
committerMarkus Scherer <markus.icu@gmail.com>
Sat, 4 May 2013 18:58:23 +0000 (18:58 +0000)
X-SVN-Rev: 33590

icu4c/source/common/uarrsort.c
icu4c/source/common/uarrsort.h

index 31ec0c121e592b1220986ce510699af2f59dc525..22c769729e00368d6feee48f230a3140f19a9c3e 100644 (file)
 #include "uarrsort.h"
 
 enum {
-    MIN_QSORT=9, /* from Knuth */
+    /**
+     * "from Knuth"
+     *
+     * A binary search over 8 items performs 4 comparisons:
+     * log2(8)=3 to subdivide, +1 to check for equality.
+     * A linear search over 8 items on average also performs 4 comparisons.
+     */
+    MIN_QSORT=9,
     STACK_ITEM_SIZE=200
 };
 
@@ -53,22 +60,14 @@ uprv_uint32Comparator(const void *context, const void *left, const void *right)
 
 /* Insertion sort using binary search --------------------------------------- */
 
-/* TODO: Make this binary search function more generally available in ICU. */
-/**
- * Much like Java Collections.binarySearch(List, Element, Comparator).
- *
- * @return the index>=0 where the item was found:
- *         the largest such index, if multiple, for stable sorting;
- *         or the index<0 for inserting the item at ~index in sorted order
- */
-static int32_t
-binarySearch(char *array, int32_t limit, int32_t itemSize, void *item,
-             UComparator *cmp, const void *context) {
+U_CAPI int32_t U_EXPORT2
+uprv_stableBinarySearch(char *array, int32_t limit, void *item, int32_t itemSize,
+                        UComparator *cmp, const void *context) {
     int32_t start=0;
     UBool found=FALSE;
 
     /* Binary search until we get down to a tiny sub-array. */
-    while((limit-start)>8) {
+    while((limit-start)>=MIN_QSORT) {
         int32_t i=(start+limit)/2;
         int32_t diff=cmp(context, item, array+i*itemSize);
         if(diff==0) {
@@ -80,6 +79,7 @@ binarySearch(char *array, int32_t limit, int32_t itemSize, void *item,
              * However, if there are many equal items, then it should be
              * faster to continue with the binary search.
              * It seems likely that we either have all unique items
+             * (where found will never become TRUE in the insertion sort)
              * or potentially many duplicates.
              */
             found=TRUE;
@@ -111,7 +111,7 @@ doInsertionSort(char *array, int32_t length, int32_t itemSize,
 
     for(j=1; j<length; ++j) {
         char *item=array+j*itemSize;
-        int32_t insertionPoint=binarySearch(array, j, itemSize, item, cmp, context);
+        int32_t insertionPoint=uprv_stableBinarySearch(array, j, item, itemSize, cmp, context);
         if(insertionPoint<0) {
             insertionPoint=~insertionPoint;
         } else {
index b9a580c7e22a84b3d268a0bf9fe4a44a11242a45..aece6da939ac09f3ecd8e83bb84f27e2751bd937 100644 (file)
@@ -1,7 +1,7 @@
 /*
 *******************************************************************************
 *
-*   Copyright (C) 2003, International Business Machines
+*   Copyright (C) 2003-2013, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 *
 *******************************************************************************
@@ -81,4 +81,21 @@ uprv_int32Comparator(const void *context, const void *left, const void *right);
 U_CAPI int32_t U_EXPORT2
 uprv_uint32Comparator(const void *context, const void *left, const void *right);
 
+/**
+ * Much like Java Collections.binarySearch(list, key, comparator).
+ *
+ * Except: Java documents "If the list contains multiple elements equal to
+ * the specified object, there is no guarantee which one will be found."
+ *
+ * This version here will return the largest index of any equal item,
+ * for use in stable sorting.
+ *
+ * @return the index>=0 where the item was found:
+ *         the largest such index, if multiple, for stable sorting;
+ *         or the index<0 for inserting the item at ~index in sorted order
+ */
+U_CAPI int32_t U_EXPORT2
+uprv_stableBinarySearch(char *array, int32_t length, void *item, int32_t itemSize,
+                        UComparator *cmp, const void *context);
+
 #endif