这是我的二进制插入排序与普通插入排序的比较。我的基准时间是决定性的。二进制版本更快。
#include <iostream>
#define NB_VALUE 1000
#define VALUE_RANGE 200
class Profiler
{
std::chrono::time_point<std::chrono::high_resolution_clock> initTime;
const char *m_name;
public:
Profiler(const char *name = nullptr): initTime(std::chrono::high_resolution_clock::now()), m_name(name){}
~Profiler()
{
if(m_name)
std::cout << m_name << " ";
auto begin = std::chrono::time_point_cast<std::chrono::microseconds>(initTime).time_since_epoch();
auto now = std::chrono::time_point_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now()).time_since_epoch();
auto duration = now - begin;
double millisecond = duration.count() * 0.001;
std::cout << millisecond << " ms\n";
}
};
template <class T>
void swap(T &t1, T &t2)
{
T tmp = t1;
t1 = t2;
t2 = tmp;
}
template<class T>
int binaryFindIndexOfSmallestBiggerOrEqual(T array[], unsigned int begin, unsigned int end, T value)
{
int delta = end - begin;
if(delta < 0)
return -1;
if(delta == 0)
{
if(array[end] > value)
return end;
else
return -1;
}
int midIndex = begin + delta / 2;
if( array[midIndex] < value )
{
return binaryFindIndexOfSmallestBiggerOrEqual(array, midIndex+1, end, value);
}
else
{
if(midIndex == 0 || array[midIndex -1] <= value)
return midIndex;
else
return binaryFindIndexOfSmallestBiggerOrEqual(array, begin, midIndex - 1, value);
}
}
template <class T>
void binaryInsertionSort(T array[], unsigned int begin, unsigned int end)
{
if(end <= begin)
return;
int sortedUpTo = begin;
int insertionIndex;
while(sortedUpTo < end)
{
if(array[sortedUpTo] < array[sortedUpTo + 1])
insertionIndex = -1;
else
insertionIndex = binaryFindIndexOfSmallestBiggerOrEqual(array, begin, sortedUpTo, array[sortedUpTo + 1]);
if(insertionIndex != -1)
{
T tmp = array[sortedUpTo + 1];
memmove(array + (insertionIndex + 1), array + (insertionIndex), sizeof(T)*(sortedUpTo - insertionIndex + 1));
array[insertionIndex] = tmp;
}
++sortedUpTo;
}
}
template <class T>
void insertionSort(T array[], unsigned int begin, unsigned int end)
{
for (int i = begin + 1; i <= end; ++i)
{
for (int j = i; j > begin + 1; --j)
{
if (array[j - 1] > array[j])
swap(array[j - 1], array[j]);
else
break;
}
}
}
int main(int argc, char **argv)
{
int arrayToSort[NB_VALUE];
//******** RANDOM CASE *********
for (int i = 0; i < NB_VALUE; ++i)
arrayToSort[i] = rand() % (VALUE_RANGE + 1) * 2 - VALUE_RANGE;
Profiler *p = new Profiler();
binaryInsertionSort(arrayToSort, 0, NB_VALUE - 1);
delete p;
//Timer : 0.119ms
for (int i = 0; i < NB_VALUE; ++i)
arrayToSort[i] = rand() % (VALUE_RANGE + 1) * 2 - VALUE_RANGE;
p = new Profiler();
insertionSort(arrayToSort, 0, NB_VALUE - 1);
delete p;
//Timer : 1 989ms
//********* ALREADY SORTED CASE ************
for (int i = 0; i < NB_VALUE; ++i)
arrayToSort[i] = i;
p = new Profiler();
binaryInsertionSort(arrayToSort, 0, NB_VALUE - 1);
delete p;
//Timer : 0.003ms
for (int i = 0; i < NB_VALUE; ++i)
arrayToSort[i] = i;
p = new Profiler();
insertionSort(arrayToSort, 0, NB_VALUE - 1);
delete p;
//Timer : 0.004ms
//********* REVERSED ORDER CASE ************
for (int i = 0; i < NB_VALUE; ++i)
arrayToSort[i] = NB_VALUE - 1;
p = new Profiler();
binaryInsertionSort(arrayToSort, 0, NB_VALUE - 1);
delete p;
//Timer : 0.046ms
for (int i = 0; i < NB_VALUE; ++i)
arrayToSort[i] = NB_VALUE - i;
p = new Profiler();
insertionSort(arrayToSort, 0, NB_VALUE - 1);
delete p;
//Timer : 3 878ms
return 1;
}