简体   繁体   English

C++ 等效于 C# Array.Sort

[英]C++ equivalent of C# Array.Sort

If it exists, what would be the C++ equivalent of the C# Array.Sort<TKey,TValue>(TKey[], TValue[], Int32, Int32) ?如果存在,C# Array.Sort<TKey,TValue>(TKey[], TValue[], Int32, Int32)的 C++ 等效项是什么? I looked at the source code of the C# function but i could not work it out.我查看了 C# function 的源代码,但我无法解决。

The doc link you provided says nothing about algorithm complexity (unsurprisingly, taking into account how good is that company with providing necessary information).您提供的文档链接没有说明算法的复杂性(毫不奇怪,考虑到该公司提供必要信息的能力有多好)。 In general, this does not look doable without at least an extra O(N) space.一般来说,如果没有额外的 O(N) 空间,这看起来是不可行的。 Konrad's solution linked in comments is perhaps the cheapest one, but if elements of your arrays are small and trivial, you can sort them by eg simply putting them in a map:评论中链接的 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;
}

(Two one-liner std::transform s can be used in place of the second loop, one copies keys, the other values.) (可以使用两个单行std::transform代替第二个循环,一个复制键,另一个复制值。)

Or an array instead of a map:或者一个数组而不是 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 iterator could prove useful here, but it's not in the STL so only library-level solutions. Zip 迭代器在这里可能很有用,但它不在 STL 中,所以只有库级解决方案。

I ended up using the following code based on the .NET code.我最终使用了基于 .NET 代码的以下代码。 The main function is IntrospectiveSort :主要的 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