簡體   English   中英

C++ 等效於 C# Array.Sort

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM