Implemented quick sort. Refactored source code.
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@8839 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
+371
-174
@@ -5,13 +5,13 @@
|
|||||||
**
|
**
|
||||||
** History
|
** History
|
||||||
** 2003-2004 Initial implementation by Stefano Ceccerini.
|
** 2003-2004 Initial implementation by Stefano Ceccerini.
|
||||||
** 2004/08/03 Testing, bug fixing and implementation of quick sort by Michael Pfeiffer.
|
** 2004/08/03 Testing, bug fixing and implementation of quick sort, refactoring
|
||||||
|
** by Michael Pfeiffer.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// TODO: Implement quick sort
|
|
||||||
|
|
||||||
// Note: Method Owning() is inlined in header file ObjectList.h
|
// Note: Method Owning() is inlined in header file ObjectList.h
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include <List.h>
|
#include <List.h>
|
||||||
|
|
||||||
|
|
||||||
@@ -25,24 +25,24 @@ public:
|
|||||||
_PointerList_(int32 itemsPerBlock = 20, bool owning = false);
|
_PointerList_(int32 itemsPerBlock = 20, bool owning = false);
|
||||||
~_PointerList_();
|
~_PointerList_();
|
||||||
|
|
||||||
typedef void *(* GenericEachFunction)(void *, void *);
|
typedef void *(* GenericEachFunction)(void *item, void *arg);
|
||||||
typedef int (* GenericCompareFunction)(const void *, const void *);
|
typedef int (* GenericCompareFunction)(const void *key, const void *item);
|
||||||
typedef int (* GenericCompareFunctionWithState)(const void *, const void *,
|
typedef int (* GenericCompareFunctionWithState)(const void *key, const void *item,
|
||||||
void *);
|
void *state);
|
||||||
typedef int (* UnaryPredicateGlue)(const void *, void *);
|
typedef int (* UnaryPredicateGlue)(const void *item, void *key);
|
||||||
|
|
||||||
void *EachElement(GenericEachFunction, void *);
|
void *EachElement(GenericEachFunction, void *arg);
|
||||||
void SortItems(GenericCompareFunction);
|
void SortItems(GenericCompareFunction);
|
||||||
void SortItems(GenericCompareFunctionWithState, void *state);
|
void SortItems(GenericCompareFunctionWithState, void *state);
|
||||||
void HSortItems(GenericCompareFunction);
|
void HSortItems(GenericCompareFunction);
|
||||||
void HSortItems(GenericCompareFunctionWithState, void *state);
|
void HSortItems(GenericCompareFunctionWithState, void *state);
|
||||||
|
|
||||||
void *BinarySearch(const void *, GenericCompareFunction) const;
|
void *BinarySearch(const void *key, GenericCompareFunction) const;
|
||||||
void *BinarySearch(const void *, GenericCompareFunctionWithState, void *state) const;
|
void *BinarySearch(const void *key, GenericCompareFunctionWithState, void *state) const;
|
||||||
|
|
||||||
int32 BinarySearchIndex(const void *, GenericCompareFunction) const;
|
int32 BinarySearchIndex(const void *key, GenericCompareFunction) const;
|
||||||
int32 BinarySearchIndex(const void *, GenericCompareFunctionWithState, void *state) const;
|
int32 BinarySearchIndex(const void *key, GenericCompareFunctionWithState, void *state) const;
|
||||||
int32 BinarySearchIndexByPredicate(const void *, UnaryPredicateGlue) const;
|
int32 BinarySearchIndexByPredicate(const void *arg, UnaryPredicateGlue) const;
|
||||||
|
|
||||||
bool Owning() const;
|
bool Owning() const;
|
||||||
bool ReplaceItem(int32, void *);
|
bool ReplaceItem(int32, void *);
|
||||||
@@ -53,18 +53,339 @@ protected:
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
class AbstractPointerListHelper
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AbstractPointerListHelper() {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the index of the item that matches key or
|
||||||
|
a negative number. Then -(index+1) is the insert position
|
||||||
|
of the item not in list.
|
||||||
|
*/
|
||||||
|
int32 BinarySearchIndex(const void *key, const BList *list);
|
||||||
|
/**
|
||||||
|
Returns the item that matches key or NULL if the item could
|
||||||
|
not be found in the list.
|
||||||
|
*/
|
||||||
|
void* BinarySearch(const void *key, const BList *list);
|
||||||
|
/**
|
||||||
|
Sorts the items in list.
|
||||||
|
*/
|
||||||
|
void SortItems(BList *list);
|
||||||
|
/**
|
||||||
|
Removes the first item in list and appends it at the bottom of
|
||||||
|
the list and sorts all items but the last item.
|
||||||
|
*/
|
||||||
|
void HSortItems(BList *list);
|
||||||
|
|
||||||
// Forward declarations
|
private:
|
||||||
|
enum {
|
||||||
|
// Use insertion sort if number of elements in list is less than
|
||||||
|
// kQuickSortThreshold.
|
||||||
|
kQuickSortThreshold = 11,
|
||||||
|
// Use simple pivot element computation if number of elements in
|
||||||
|
// list is less than kPivotThreshold.
|
||||||
|
kPivotThreshold = 5,
|
||||||
|
};
|
||||||
|
|
||||||
static void *BinarySearch(const void *key, const void **items,
|
// Methods that do the actual work:
|
||||||
int32 numItems,
|
inline void Swap(void **items, int32 i, int32 j);
|
||||||
_PointerList_::GenericCompareFunction compareFunc,
|
|
||||||
int32& index);
|
|
||||||
|
|
||||||
static void *BinarySearch(const void *key, const void **items,
|
void* BinarySearch(const void *key, const void **items, int32 numItems, int32 &index);
|
||||||
int32 numItems,
|
void InsertionSort(void **items, int32 numItems);
|
||||||
_PointerList_::GenericCompareFunctionWithState compareFunc, void *state,
|
inline void InsertionSort(void **items, int32 low, int32 high);
|
||||||
int32& index);
|
int32 ChoosePivot(void **items, int32 low, int32 high);
|
||||||
|
int32 Partition(void **items, int32 low, int32 high, bool &isSorted);
|
||||||
|
void QuickSort(void **items, int32 low, int32 high);
|
||||||
|
|
||||||
|
// Method to be implemented by sub classes
|
||||||
|
int virtual Compare(const void *key, const void* item) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void AbstractPointerListHelper::Swap(void **items, int32 i, int32 j)
|
||||||
|
{
|
||||||
|
void *swap = items[i];
|
||||||
|
items[i] = items[j];
|
||||||
|
items[j] = swap;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32 AbstractPointerListHelper::BinarySearchIndex(const void* key, const BList *list)
|
||||||
|
{
|
||||||
|
int32 index;
|
||||||
|
const void **items = static_cast<const void**>(list->Items());
|
||||||
|
BinarySearch(key, items, list->CountItems(), index);
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void* AbstractPointerListHelper::BinarySearch(const void* key, const BList *list)
|
||||||
|
{
|
||||||
|
int32 index;
|
||||||
|
const void **items = static_cast<const void**>(list->Items());
|
||||||
|
return BinarySearch(key, items, list->CountItems(), index);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void AbstractPointerListHelper::SortItems(BList *list)
|
||||||
|
{
|
||||||
|
void **items = static_cast<void**>(list->Items());
|
||||||
|
QuickSort(items, 0, list->CountItems()-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void AbstractPointerListHelper::HSortItems(BList *list)
|
||||||
|
{
|
||||||
|
void **items = static_cast<void**>(list->Items());
|
||||||
|
int32 numItems = list->CountItems();
|
||||||
|
if (numItems > 1) {
|
||||||
|
// swap last with first item
|
||||||
|
Swap(items, 0, numItems-1);
|
||||||
|
}
|
||||||
|
// sort all items but last item
|
||||||
|
QuickSort(items, 0, numItems-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void* AbstractPointerListHelper::BinarySearch(const void* key, const void** items, int32 numItems, int32& index)
|
||||||
|
{
|
||||||
|
int32 low = 0;
|
||||||
|
int32 high = numItems-1;
|
||||||
|
int result = 0;
|
||||||
|
index = 0;
|
||||||
|
while (low <= high) {
|
||||||
|
index = (low + high) / 2;
|
||||||
|
const void* item = items[index];
|
||||||
|
result = Compare(key, item);
|
||||||
|
if (result < 0) {
|
||||||
|
// key < item
|
||||||
|
high = index - 1;
|
||||||
|
} else if (result > 0) {
|
||||||
|
// key > item
|
||||||
|
low = index + 1;
|
||||||
|
} else {
|
||||||
|
// key == item
|
||||||
|
return static_cast<void*>(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// item not found
|
||||||
|
if (result > 0) {
|
||||||
|
// key > last item (= items[index])
|
||||||
|
// insert position for key is after last item
|
||||||
|
index ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
index = -(index+1);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32 AbstractPointerListHelper::ChoosePivot(void **items, int32 low, int32 high)
|
||||||
|
{
|
||||||
|
if (kPivotThreshold <= kQuickSortThreshold ||
|
||||||
|
high - low > kPivotThreshold) {
|
||||||
|
assert(high - low > kPivotThreshold);
|
||||||
|
// choose the middle item of three items
|
||||||
|
int32 mid = (low + high) / 2;
|
||||||
|
|
||||||
|
void* first = items[low];
|
||||||
|
void* middle = items[mid];
|
||||||
|
void* last = items[high];
|
||||||
|
|
||||||
|
if (Compare(first, middle) <= 0) {
|
||||||
|
// first <= middle
|
||||||
|
if (Compare(middle, last) <= 0) {
|
||||||
|
// first <= middle <= last
|
||||||
|
return mid;
|
||||||
|
}
|
||||||
|
// first <= middle and last < middle
|
||||||
|
if (Compare(first, last) <= 0) {
|
||||||
|
// first <= last < middle
|
||||||
|
return high;
|
||||||
|
}
|
||||||
|
// last < first <= middle
|
||||||
|
return low;
|
||||||
|
}
|
||||||
|
// middle < first
|
||||||
|
if (Compare(first, last) <= 0) {
|
||||||
|
// middle < first <= last
|
||||||
|
return low;
|
||||||
|
}
|
||||||
|
// middle < first and last < first
|
||||||
|
if (Compare(middle, last) <= 0) {
|
||||||
|
// middle <= last < first
|
||||||
|
return high;
|
||||||
|
}
|
||||||
|
// last < middle < first
|
||||||
|
return mid;
|
||||||
|
} else {
|
||||||
|
// choose the middle element to avoid O(n^2) for an already sorted list
|
||||||
|
return (low + high) / 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32 AbstractPointerListHelper::Partition(void **items, int32 low, int32 high, bool& isSorted)
|
||||||
|
{
|
||||||
|
assert(low < high);
|
||||||
|
int32 left = low;
|
||||||
|
int32 right = high;
|
||||||
|
int32 pivot = ChoosePivot(items, low, high);
|
||||||
|
void *pivotItem = items[pivot];
|
||||||
|
|
||||||
|
// Optimization: Check if all items are equal. We get this almost for free.
|
||||||
|
// Searching the first item that does not belong to the left list has to
|
||||||
|
// be done anyway.
|
||||||
|
int32 result;
|
||||||
|
isSorted = true;
|
||||||
|
// Search first item in left part that does not belong to this part
|
||||||
|
// (where item > pivotItem)
|
||||||
|
while (left < right && (result = Compare(items[left], pivotItem)) <= 0) {
|
||||||
|
left ++;
|
||||||
|
if (result != 0) {
|
||||||
|
isSorted = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isSorted && left == right && Compare(items[right], pivotItem) == 0) {
|
||||||
|
return low;
|
||||||
|
}
|
||||||
|
// End of optimization
|
||||||
|
isSorted = false;
|
||||||
|
|
||||||
|
// pivot element has to be first element in list
|
||||||
|
if (low != pivot) {
|
||||||
|
Swap(items, low, pivot);
|
||||||
|
}
|
||||||
|
|
||||||
|
// now partion the array in a left part where item <= pivotItem
|
||||||
|
// and a right part where item > pivotItem
|
||||||
|
do {
|
||||||
|
// search first item in left part that does not belong to this part
|
||||||
|
// (where item > pivotItem)
|
||||||
|
while (left < right && Compare(items[left], pivotItem) <= 0) {
|
||||||
|
left ++;
|
||||||
|
}
|
||||||
|
// search first item (from right to left) in right part that does not belong
|
||||||
|
// to this part (where item <= pivotItem). This holds at least for pivot
|
||||||
|
// element at top of list! No array bounds check needed!
|
||||||
|
while (Compare(items[right], pivotItem) > 0) {
|
||||||
|
right --;
|
||||||
|
}
|
||||||
|
if (left < right) {
|
||||||
|
// now swap the items to the proper part
|
||||||
|
Swap(items, left, right);
|
||||||
|
}
|
||||||
|
} while (left < right);
|
||||||
|
// place pivotItem between left and right part
|
||||||
|
items[low] = items[right];
|
||||||
|
items[right] = pivotItem;
|
||||||
|
return right;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void AbstractPointerListHelper::InsertionSort(void **items, int32 numItems)
|
||||||
|
{
|
||||||
|
for (int32 i = 1; i < numItems; i ++) {
|
||||||
|
// treat list[0 .. i-1] as sorted
|
||||||
|
void* item = items[i];
|
||||||
|
// insert item at right place in list[0..i]
|
||||||
|
int32 j = i;
|
||||||
|
void* prev = items[j-1];
|
||||||
|
while (Compare(prev, item) > 0) {
|
||||||
|
items[j] = prev;
|
||||||
|
j --;
|
||||||
|
if (j <= 0) break;
|
||||||
|
prev = items[j-1];
|
||||||
|
}
|
||||||
|
items[j] = item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void AbstractPointerListHelper::InsertionSort(void **items, int32 low, int32 high)
|
||||||
|
{
|
||||||
|
InsertionSort(&items[low], high - low + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void AbstractPointerListHelper::QuickSort(void **items, int32 low, int32 high)
|
||||||
|
{
|
||||||
|
if (low < high) {
|
||||||
|
if (high - low < kQuickSortThreshold) {
|
||||||
|
InsertionSort(items, low, high);
|
||||||
|
} else {
|
||||||
|
bool isSorted;
|
||||||
|
int pivot = Partition(items, low, high, isSorted);
|
||||||
|
if (isSorted) return;
|
||||||
|
|
||||||
|
QuickSort(items, low, pivot - 1);
|
||||||
|
QuickSort(items, pivot + 1, high);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class PointerListHelper : public AbstractPointerListHelper
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PointerListHelper(_PointerList_::GenericCompareFunction compareFunc)
|
||||||
|
: fCompareFunc(compareFunc)
|
||||||
|
{
|
||||||
|
// nothing to do
|
||||||
|
}
|
||||||
|
|
||||||
|
int Compare(const void *a, const void *b) {
|
||||||
|
return fCompareFunc(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
_PointerList_::GenericCompareFunction fCompareFunc;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class PointerListHelperWithState : public AbstractPointerListHelper
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PointerListHelperWithState(
|
||||||
|
_PointerList_::GenericCompareFunctionWithState compareFunc,
|
||||||
|
void* state)
|
||||||
|
: fCompareFunc(compareFunc)
|
||||||
|
, fState(state)
|
||||||
|
{
|
||||||
|
// nothing to do
|
||||||
|
}
|
||||||
|
|
||||||
|
int Compare(const void *a, const void *b) {
|
||||||
|
return fCompareFunc(a, b, fState);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
_PointerList_::GenericCompareFunctionWithState fCompareFunc;
|
||||||
|
void* fState;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class PointerListHelperUsePredicate : public AbstractPointerListHelper
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PointerListHelperUsePredicate(
|
||||||
|
_PointerList_::UnaryPredicateGlue predicate)
|
||||||
|
: fPredicate(predicate)
|
||||||
|
{
|
||||||
|
// nothing to do
|
||||||
|
}
|
||||||
|
|
||||||
|
int Compare(const void *arg, const void *item) {
|
||||||
|
// need to adapt arguments and return value
|
||||||
|
return -fPredicate(item, static_cast<void*>(arg));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
_PointerList_::UnaryPredicateGlue fPredicate;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// Implementation of class _PointerList_
|
// Implementation of class _PointerList_
|
||||||
@@ -93,19 +414,20 @@ _PointerList_::~_PointerList_()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Note: function pointers must not be NULL!!!
|
||||||
|
|
||||||
void *
|
void *
|
||||||
_PointerList_::EachElement(GenericEachFunction function, void *arg)
|
_PointerList_::EachElement(GenericEachFunction function, void *arg)
|
||||||
{
|
{
|
||||||
int32 numItems = CountItems();
|
int32 numItems = CountItems();
|
||||||
void *result = NULL;
|
void *result = NULL;
|
||||||
|
|
||||||
if (function) {
|
for (int32 index = 0; index < numItems; index++) {
|
||||||
for (int32 index = 0; index < numItems; index++) {
|
result = function(ItemAtFast(index), arg);
|
||||||
result = function(ItemAtFast(index), arg);
|
if (result != NULL)
|
||||||
if (result != NULL)
|
break;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,85 +435,40 @@ _PointerList_::EachElement(GenericEachFunction function, void *arg)
|
|||||||
void
|
void
|
||||||
_PointerList_::SortItems(GenericCompareFunction compareFunc)
|
_PointerList_::SortItems(GenericCompareFunction compareFunc)
|
||||||
{
|
{
|
||||||
|
PointerListHelper helper(compareFunc);
|
||||||
if (compareFunc) {
|
helper.SortItems(this);
|
||||||
int32 numItems = CountItems();
|
|
||||||
if (numItems > 1) {
|
|
||||||
void **items = (void **)Items();
|
|
||||||
for (int32 i = 0; i < numItems - 1; i++) {
|
|
||||||
for (int32 j = 0; j < numItems - 1 - i; j++) {
|
|
||||||
if (compareFunc(items[j + 1], items[j]) < 0) {
|
|
||||||
void *tmp = items[j];
|
|
||||||
items[j] = items[j + 1];
|
|
||||||
items[j + 1] = tmp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
_PointerList_::SortItems(GenericCompareFunctionWithState compareFunc, void *state)
|
_PointerList_::SortItems(GenericCompareFunctionWithState compareFunc, void *state)
|
||||||
{
|
{
|
||||||
if (compareFunc) {
|
PointerListHelperWithState helper(compareFunc, state);
|
||||||
int32 numItems = CountItems();
|
helper.SortItems(this);
|
||||||
if (numItems > 1) {
|
|
||||||
void **items = (void **)Items();
|
|
||||||
for (int32 i = 0; i < numItems - 1; i++) {
|
|
||||||
for (int32 j = 0; j < numItems - 1 - i; j++) {
|
|
||||||
if (compareFunc(items[j + 1], items[j], state) < 0) {
|
|
||||||
void *tmp = items[j];
|
|
||||||
items[j] = items[j + 1];
|
|
||||||
items[j + 1] = tmp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
_PointerList_::HSortItems(GenericCompareFunction sortFunction)
|
_PointerList_::HSortItems(GenericCompareFunction compareFunc)
|
||||||
{
|
{
|
||||||
const bool hasItems = !IsEmpty();
|
PointerListHelper helper(compareFunc);
|
||||||
void* firstItem = NULL;
|
helper.HSortItems(this);
|
||||||
if (hasItems) {
|
|
||||||
// append first item after sorting the list
|
|
||||||
firstItem = ItemAt(0);
|
|
||||||
RemoveItem((int32)0);
|
|
||||||
}
|
|
||||||
SortItems(sortFunction);
|
|
||||||
if (hasItems) {
|
|
||||||
AddItem(firstItem);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
_PointerList_::HSortItems(GenericCompareFunctionWithState sortFunc, void *state)
|
_PointerList_::HSortItems(GenericCompareFunctionWithState compareFunc, void *state)
|
||||||
{
|
{
|
||||||
const bool hasItems = !IsEmpty();
|
PointerListHelperWithState helper(compareFunc, state);
|
||||||
void* firstItem = NULL;
|
helper.HSortItems(this);
|
||||||
if (hasItems) {
|
|
||||||
// append first item after sorting the list
|
|
||||||
firstItem = ItemAt(0);
|
|
||||||
RemoveItem((int32)0);
|
|
||||||
}
|
|
||||||
SortItems(sortFunc, state);
|
|
||||||
if (hasItems) {
|
|
||||||
AddItem(firstItem);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void *
|
void *
|
||||||
_PointerList_::BinarySearch(const void *key, GenericCompareFunction compareFunc) const
|
_PointerList_::BinarySearch(const void *key, GenericCompareFunction compareFunc) const
|
||||||
{
|
{
|
||||||
int32 index;
|
PointerListHelper helper(compareFunc);
|
||||||
return ::BinarySearch(key, (const void **)Items(), CountItems(), compareFunc, index);
|
return helper.BinarySearch(key, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -199,17 +476,16 @@ void *
|
|||||||
_PointerList_::BinarySearch(const void *key,
|
_PointerList_::BinarySearch(const void *key,
|
||||||
GenericCompareFunctionWithState compareFunc, void *state) const
|
GenericCompareFunctionWithState compareFunc, void *state) const
|
||||||
{
|
{
|
||||||
int32 index;
|
PointerListHelperWithState helper(compareFunc, state);
|
||||||
return ::BinarySearch(key, (const void**)Items(), CountItems(), compareFunc, state, index);
|
return helper.BinarySearch(key, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int32
|
int32
|
||||||
_PointerList_::BinarySearchIndex(const void *key, GenericCompareFunction compareFunc) const
|
_PointerList_::BinarySearchIndex(const void *key, GenericCompareFunction compareFunc) const
|
||||||
{
|
{
|
||||||
int32 index;
|
PointerListHelper helper(compareFunc);
|
||||||
::BinarySearch(key, (const void**)Items(), CountItems(), compareFunc, index);
|
return helper.BinarySearchIndex(key, this);
|
||||||
return index;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -217,38 +493,16 @@ int32
|
|||||||
_PointerList_::BinarySearchIndex(const void *key,
|
_PointerList_::BinarySearchIndex(const void *key,
|
||||||
GenericCompareFunctionWithState compareFunc, void *state) const
|
GenericCompareFunctionWithState compareFunc, void *state) const
|
||||||
{
|
{
|
||||||
int32 index;
|
PointerListHelperWithState helper(compareFunc, state);
|
||||||
::BinarySearch(key, (const void**)Items(), CountItems(), compareFunc, state, index);
|
return helper.BinarySearchIndex(key, this);
|
||||||
return index;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int32
|
int32
|
||||||
_PointerList_::BinarySearchIndexByPredicate(const void *key, UnaryPredicateGlue predicate) const
|
_PointerList_::BinarySearchIndexByPredicate(const void *key, UnaryPredicateGlue predicate) const
|
||||||
{
|
{
|
||||||
void** items = (void**)Items();
|
PointerListHelperUsePredicate helper(predicate);
|
||||||
int32 low = 0;
|
return helper.BinarySearchIndex(key, this);
|
||||||
int32 high = CountItems()-1;
|
|
||||||
int result = 0;
|
|
||||||
int index = 0;
|
|
||||||
while (low <= high) {
|
|
||||||
index = (low + high) / 2;
|
|
||||||
const void* item = items[index];
|
|
||||||
result = predicate(item, (void*)key);
|
|
||||||
if (result > 0) {
|
|
||||||
high = index - 1;
|
|
||||||
} else if (result < 0) {
|
|
||||||
low = index + 1;
|
|
||||||
} else {
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result < 0) {
|
|
||||||
index ++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return -(index+1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@@ -263,60 +517,3 @@ _PointerList_::ReplaceItem(int32 index, void *newItem)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implementation of static functions
|
|
||||||
|
|
||||||
static void * BinarySearch(const void* key, const void** items, int32 numItems,
|
|
||||||
_PointerList_::GenericCompareFunction compareFunc, int32& index)
|
|
||||||
{
|
|
||||||
int32 low = 0;
|
|
||||||
int32 high = numItems-1;
|
|
||||||
int result = 0;
|
|
||||||
index = 0;
|
|
||||||
while (low <= high) {
|
|
||||||
index = (low + high) / 2;
|
|
||||||
const void* item = items[index];
|
|
||||||
result = compareFunc(key, item);
|
|
||||||
if (result < 0) {
|
|
||||||
high = index - 1;
|
|
||||||
} else if (result > 0) {
|
|
||||||
low = index + 1;
|
|
||||||
} else {
|
|
||||||
return (void*)item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result > 0) {
|
|
||||||
index ++;
|
|
||||||
}
|
|
||||||
|
|
||||||
index = -(index+1);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void * BinarySearch(const void* key, const void** items, int32 numItems,
|
|
||||||
_PointerList_::GenericCompareFunctionWithState compareFunc, void* state, int32& index)
|
|
||||||
{
|
|
||||||
int32 low = 0;
|
|
||||||
int32 high = numItems-1;
|
|
||||||
int result = 0;
|
|
||||||
index = 0;
|
|
||||||
while (low <= high) {
|
|
||||||
index = (low + high) / 2;
|
|
||||||
const void* item = items[index];
|
|
||||||
result = compareFunc(key, item, state);
|
|
||||||
if (result < 0) {
|
|
||||||
high = index - 1;
|
|
||||||
} else if (result > 0) {
|
|
||||||
low = index + 1;
|
|
||||||
} else {
|
|
||||||
return (void*)item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result > 0) {
|
|
||||||
index ++;
|
|
||||||
}
|
|
||||||
|
|
||||||
index = -(index+1);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user