[英]C++ equivalent of C# Array.Sort
如果存在,C# Array.Sort<TKey,TValue>(TKey[], TValue[], Int32, Int32)
的 C++ 等效項是什么? 我查看了 C# function 的源代碼,但我無法解決。
您提供的文檔鏈接沒有說明算法的復雜性(毫不奇怪,考慮到該公司提供必要信息的能力有多好)。 一般來說,如果沒有額外的 O(N) 空間,這看起來是不可行的。 評論中鏈接的 Konrad 解決方案可能是最便宜的解決方案,但如果您的 arrays 的元素很小且微不足道,您可以通過例如簡單地將它們放入 map 來對它們進行排序:
std::multimap<TKey, TValue> items;
for(std::size_t i{}; i < keys.size(); ++i) {
items.emplace(std::move(keys[i]), std::move(values[i]));
}
std::size_t i{};
for(auto &&kv: items) {
keys[i] = kv.first;
keys[i] = std::move(kv.second);
++i;
}
(可以使用兩個單行std::transform
代替第二個循環,一個復制鍵,另一個復制值。)
或者一個數組而不是 map:
std::vector<std::pair<TKey, TValue>> items(keys.size());
std::transform(
std::make_move_iterator(keys.begin()),
std::make_move_iterator(keys.end()),
std::make_move_iterator(values.begin()),
items.begin(),
(auto &&k, auto &&v) { return std::pair{std::move(k), std::move(v); });
std::sort(items.begin(), items.end(), [](auto const &l, auto const &r) {
return l.first < r.first;
});
// Now copy them back, like above.
Zip 迭代器在這里可能很有用,但它不在 STL 中,所以只有庫級解決方案。
我最終使用了基於 .NET 代碼的以下代碼。 主要的 function 是IntrospectiveSort
:
static void IntrospectiveSort(int keys[], double items[], int left, int right) {
// Make sure left != right in your own code.
_ASSERTE(keys != NULL && left < right);
int length = right - left + 1;
if (length < 2)
return;
IntroSort(keys, items, left, right, 2 * FloorLog2(length));
}
static const int introsortSizeThreshold = 16;
static int FloorLog2(int n)
{
int result = 0;
while (n >= 1)
{
result++;
n = n / 2;
}
return result;
}
inline static void SwapIfGreaterWithItems(int keys[], double items[], int a, int b) {
if (a != b) {
if (keys[a] > keys[b]) {
int key = keys[a];
keys[a] = keys[b];
keys[b] = key;
if (items != NULL) {
double item = items[a];
items[a] = items[b];
items[b] = item;
}
}
}
}
static void IntroSort(int keys[], double items[], int lo, int hi, int depthLimit)
{
while (hi > lo)
{
int partitionSize = hi - lo + 1;
if (partitionSize <= introsortSizeThreshold)
{
if (partitionSize == 1)
{
return;
}
if (partitionSize == 2)
{
SwapIfGreaterWithItems(keys, items, lo, hi);
return;
}
if (partitionSize == 3)
{
SwapIfGreaterWithItems(keys, items, lo, hi - 1);
SwapIfGreaterWithItems(keys, items, lo, hi);
SwapIfGreaterWithItems(keys, items, hi - 1, hi);
return;
}
InsertionSort(keys, items, lo, hi);
return;
}
if (depthLimit == 0)
{
Heapsort(keys, items, lo, hi);
return;
}
depthLimit--;
int p = PickPivotAndPartition(keys, items, lo, hi);
IntroSort(keys, items, p + 1, hi, depthLimit);
hi = p - 1;
}
return;
}
static void Swap(int keys[], double items[], int i, int j)
{
int t = keys[i];
keys[i] = keys[j];
keys[j] = t;
if (items != NULL)
{
double item = items[i];
items[i] = items[j];
items[j] = item;
}
}
static int PickPivotAndPartition(int keys[], double items[], int lo, int hi)
{
// Compute median-of-three. But also partition them, since we've done the comparison.
int mid = lo + (hi - lo) / 2;
// Sort lo, mid and hi appropriately, then pick mid as the pivot.
SwapIfGreaterWithItems(keys, items, lo, mid);
SwapIfGreaterWithItems(keys, items, lo, hi);
SwapIfGreaterWithItems(keys, items, mid, hi);
int pivot = keys[mid];
Swap(keys, items, mid, hi - 1);
int left = lo, right = hi - 1; // We already partitioned lo and hi and put the pivot in hi - 1. And we pre-increment & decrement below.
while (left < right)
{
while (left < (hi - 1) && keys[++left] < pivot);
while (right > lo && pivot < keys[--right]);
if ((left >= right))
break;
Swap(keys, items, left, right);
}
// Put pivot in the right location.
Swap(keys, items, left, (hi - 1));
return left;
}
static void Heapsort(int keys[], double items[], int lo, int hi)
{
int n = hi - lo + 1;
for (int i = n / 2; i >= 1; i = i - 1)
{
DownHeap(keys, items, i, n, lo);
}
for (int i = n; i > 1; i = i - 1)
{
Swap(keys, items, lo, lo + i - 1);
DownHeap(keys, items, 1, i - 1, lo);
}
}
static void DownHeap(int keys[], double items[], int i, int n, int lo)
{
int d = keys[lo + i - 1];
double di = (items != NULL) ? items[lo + i - 1] : NULL;
int child;
while (i <= n / 2)
{
child = 2 * i;
if (child < n && keys[lo + child - 1] < keys[lo + child])
{
child++;
}
if (!(d < keys[lo + child - 1]))
break;
keys[lo + i - 1] = keys[lo + child - 1];
if (items != NULL)
items[lo + i - 1] = items[lo + child - 1];
i = child;
}
keys[lo + i - 1] = d;
if (items != NULL)
items[lo + i - 1] = di;
}
static void InsertionSort(int keys[], double items[], int lo, int hi)
{
int i, j;
int t;
double ti = NULL;
for (i = lo; i < hi; i++)
{
j = i;
t = keys[i + 1];
if (items != NULL)
ti = items[i + 1];
while (j >= lo && t < keys[j])
{
keys[j + 1] = keys[j];
if (items != NULL)
items[j + 1] = items[j];
j--;
}
keys[j + 1] = t;
if (items != NULL)
items[j + 1] = ti;
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.