声明
#pragma once
#include<random>
class Sort
{
#define DefaultAscending [](auto Left, auto Right) ->bool { return (Left > Right); }
#define DefaultDescending [](auto Left, auto Right) ->bool { return (Left < Right); }
#define QuickEqualAscending [](auto Left, auto Right) ->bool { return (Left >= Right); }
#define QuickEqualDescending [](auto Left, auto Right) ->bool { return (Left <= Right); }
public:
static constexpr size_t SmallArraySize = 10u;
template<typename T>
static void Bubble(
T* Array,
const size_t& size,
bool (*compare)(const T& Left, const T& Right) = DefaultAscending);
template<typename T>
static void Cocktail(
T* Array,
size_t size,
bool (*compare)(const T& Left, const T& Right) = DefaultAscending);
template<typename T>
static void DirectSelection(
T* Array,
const size_t& size,
bool (*compare)(const T& Left, const T& Right) = DefaultAscending);
template<typename T>
static void TwoWaySelection(
T* Array,
size_t size,
bool (*compare)(const T& Left, const T& Right) = DefaultAscending);
template<typename T>
static void QuickDigging(
T* Array,
const size_t& size,
bool (*compare)(const T& Left, const T& Right) = QuickEqualAscending);
template<typename T>
static void QuickDigging2(
T* Array,
const size_t& size,
bool (*compare)(const T& Left, const T& Right) = QuickEqualAscending);
template<typename T>
static void Insertion(
T* Array,
const size_t& size,
bool (*compare)(const T& Left, const T& Right) = DefaultAscending);
template<typename T>
static void Bubble(
T *Array,
const size_t &Start,
const size_t &End,
bool (*compare)(const T &Left,const T &Right) = DefaultAscending);
template<typename T>
static void Cocktail(
T* Array,
size_t Start,
size_t End,
bool (*compare)(const T& Left, const T& Right) = DefaultAscending);
template<typename T>
static void DirectSelection(
T* Array,
const size_t& Start,
const size_t& End,
bool (*compare)(const T& Left, const T& Right) = DefaultAscending);
template<typename T>
static void TwoWaySelection(
T* Array,
size_t Start,
size_t End,
bool (*compare)(const T& Left, const T& Right) = DefaultAscending);
template<typename T>
static void QuickDigging(
T* Array,
const size_t& Start,
const size_t& End,
bool (*compare)(const T& Left, const T& Right) = QuickEqualAscending);
template<typename T>
static void QuickDigging2(
T* Array,
const size_t& Start,
const size_t& End,
bool (*compare)(const T& Left, const T& Right) = QuickEqualAscending);
template<typename T>
static void Insertion(
T* Array,
const size_t& Start,
const size_t& End,
bool (*compare)(const T& Left, const T& Right) = DefaultAscending);
};
定义
template<typename T>
inline void Sort::Bubble(T* Array, const size_t& size, bool(*compare)(const T& Left, const T& Right))
{
Bubble(Array, 0u, size, compare);
}
template<typename T>
inline void Sort::Cocktail(T* Array, size_t size, bool(*compare)(const T& Left, const T& Right))
{
Cocktail(Array, 0u, size, compare);
}
template<typename T>
inline void Sort::DirectSelection(T* Array, const size_t& size, bool(*compare)(const T& Left, const T& Right))
{
DirectSelection(Array, 0u, size, compare);
}
template<typename T>
inline void Sort::TwoWaySelection(T* Array, size_t size, bool(*compare)(const T& Left, const T& Right))
{
TwoWaySelection(Array, 0u, size, compare);
}
template<typename T>
inline void Sort::QuickDigging(T* Array, const size_t& size, bool(*compare)(const T& Left, const T& Right))
{
QuickDigging(Array, 0u, size, compare);
}
template<typename T>
inline void Sort::QuickDigging2(T* Array, const size_t& size, bool(*compare)(const T& Left, const T& Right))
{
QuickDigging2(Array, 0u, size, compare);
}
template<typename T>
inline void Sort::Insertion(T* Array, const size_t& size, bool(*compare)(const T& Left, const T& Right))
{
Insertion(Array, 0u, size, compare);
}
template<typename T>
inline void Sort::Bubble(
T *Array,
const size_t &Start,
const size_t &End,
bool (*compare)(const T &Left, const T &Right))
{
bool IsOk;
T tempValue;
for (size_t i = Start; i < End; ++i)
{
IsOk = true;
for (size_t j = Start; j < (End - 1u - i); ++j)
{
if (compare(Array[j], Array[j + 1u]))
{
tempValue = Array[j];
Array[j] = Array[j + 1];
Array[j + 1] = tempValue;
IsOk = false;
}
}
if (IsOk)break;
}
}
template<typename T>
inline void Sort::Cocktail(
T* Array,
size_t Start,
size_t End,
bool(*compare)(const T& Left, const T& Right))
{
bool IsOk;
T tempValue;
while (Start < (End - 1u))
{
IsOk = true;
for (size_t i = Start; i < (End - 1u); ++i)
{
if (compare(Array[i], Array[i + 1u]))
{
tempValue = Array[i];
Array[i] = Array[i + 1];
Array[i + 1] = tempValue;
IsOk = false;
}
}
if (IsOk)break;
--End;
IsOk = true;
for (size_t i = (End - 1u); i > Start; --i)
{
if (compare(Array[i - 1], Array[i]))
{
tempValue = Array[i - 1];
Array[i - 1] = Array[i];
Array[i] = tempValue;
IsOk = false;
}
}
if (IsOk)break;
++Start;
}
}
template<typename T>
inline void Sort::DirectSelection(
T* Array,
const size_t& Start,
const size_t& End,
bool(*compare)(const T& Left, const T& Right))
{
T tempValue;
for (size_t i = Start, index; i < End; ++i)
{
index = i;
for (size_t j = i + 1u; j < End; ++j)
{
if (compare(Array[index], Array[j]))
{
index = j;
}
}
if (index > i)
{
tempValue = Array[i];
Array[i] = Array[index];
Array[index] = tempValue;
}
}
}
template<typename T>
inline void Sort::TwoWaySelection(
T* Array,
size_t Start,
size_t End,
bool(*compare)(const T& Left, const T& Right))
{
T tempValue;
size_t indexL,indexR;
while (Start < (End - 1u))
{
indexL = indexR = Start;
for (size_t i = Start + 1u; i < End; ++i)
{
if (compare(Array[indexL], Array[i]))
{
indexL = i;
}
if (compare(Array[i], Array[indexR]))
{
indexR = i;
}
}
if (indexL > Start)
{
tempValue = Array[Start];
Array[Start] = Array[indexL];
Array[indexL] = tempValue;
}
++Start;
if ((indexR != (Start - 1u)) || (indexL != (End - 1u)))
{
if (indexR == (Start - 1u))
++indexR;
if (indexR < (End - 1u))
{
tempValue = Array[End - 1u];
Array[End - 1u] = Array[indexR];
Array[indexR] = tempValue;
}
}
--End;
}
}
template<typename T>
inline void Sort::QuickDigging(
T* Array,
const size_t& Start,
const size_t& End,
bool(*compare)(const T& Left, const T& Right))
{
auto findPivot = [&Array,&compare](size_t left,size_t right)
{
static std::random_device Rand;
size_t randId = (Rand() % (right - left) + left);
T pivot = Array[randId];
Array[randId] = Array[left];
--right;
while (left < right)
{
while ((left < right) && compare(Array[right], pivot)) --right;
Array[left] = Array[right];
while ((left < right) && compare(pivot, Array[left])) ++left;
Array[right] = Array[left];
}
Array[left] = pivot;
return left;
};
if ((Start + 1u) < End)
{
size_t pivotId = findPivot(Start, End);
QuickDigging(Array, Start, pivotId, compare);
QuickDigging(Array, pivotId + 1u, End, compare);
}
}
template<typename T>
inline void Sort::QuickDigging2(
T* Array,
const size_t& Start,
const size_t& End,
bool(*compare)(const T& Left, const T& Right))
{
if ((End - Start) > SmallArraySize)
{
QuickDigging(Array, Start, End, compare);
}
else
{
Insertion(Array, Start, End, compare);
return;
}
}
template<typename T>
inline void Sort::Insertion(
T* Array,
const size_t& Start,
const size_t& End,
bool(*compare)(const T& Left, const T& Right))
{
T tempValue;
for (size_t i = Start, targetPos; i < (End - 1u); ++i)
{
for (targetPos = (i + 1u); targetPos > 0u; --targetPos)
{
if (!compare(Array[targetPos - 1u], Array[i + 1u]))
break;
}
if (targetPos < (i + 1u))
{
tempValue = Array[i + 1u];
std::copy(Array + targetPos, Array + (i + 1u), Array + (targetPos + 1u));
Array[targetPos] = tempValue;
}
}
}