首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >整数个数固定的排序向量

整数个数固定的排序向量
EN

Stack Overflow用户
提问于 2015-11-15 21:37:44
回答 5查看 446关注 0票数 3

向量列表vl的最大长度为100000000。101个不同的整数值。最好和最快的排序算法是什么?

我尝试过计数排序,(存储桶排序),...,但它们不够快。每个整数(+ -)都是有效的。100000000,101个不同的整数是随机生成的。感谢您的回复!我最好的算法大约是0.620s。

EN

回答 5

Stack Overflow用户

发布于 2015-11-15 22:28:12

使用unorder_set查找唯一值,然后将这些唯一值放入vector并对其进行排序;然后将原始值放入unorder_multiset以计算值,如下所示:

代码语言:javascript
运行
复制
vector<int> v;
// fill v with values
unordered_set<int> s(begin(v), end(v));
vector<int> sorted_v(begin(s), end(s));
sort(begin(sorted_v), end(sorted_v));
unordered_multiset<int> v_count(begin(v), end(v));
for (size_t i = 0; i < sorted_v.size(); ++i)
    cout << "For the " << i << "th value == " << sorted_v[i] << " there are " << v_count.count(v[i]) << " of them." << endl;
票数 1
EN

Stack Overflow用户

发布于 2015-11-15 22:50:21

根据wiki (参见算法对照表),我们应该使用计数排序,因为我们没有太多不同的值。

首先,我假设我们的值是int 0-100,并使用以下代码:

代码语言:javascript
运行
复制
void sort(std::vector<int>& v)
{
    double start = std::clock();
    int* table = new int[MAX];
    for (int i = 0; i < MAX; ++i)
    {
        table[i] = 0;
    }
    for (int i = 0; i < size; ++i)
    {
        ++table[v[i]];
    }
    int cur = 0;
    for (int i = 0; i < MAX; ++i)
    {
        for (int j = 0; j < table[i]; ++j)
        {
            v[cur++] = i;
        }
    }
    delete[] table;
    std::cout << "count sort over char array took " << (std::clock() - start) / CLOCKS_PER_SEC << " s" << std::endl;
}

这段代码在我的计算机上使用0.149s,而不是std::sort使用的3.002s

这是counting sort的经典实现,但现在尝试加快速度,删除一些多余的计算:

代码语言:javascript
运行
复制
void sort6(int* v, int size)
{
    double start = std::clock();
    int* table = new int[MAX];
    for (int i = 0; i < MAX; ++i)
    {
        table[i] = 0;
    }
    int* end = v + size;
    for (int* vi = v; vi < end; ++vi)
    {
        ++table[*vi];
    }
    int* cur = v;
    for (int i = 0; i < MAX; ++i)
    {
        int count = table[i];
        for (int j = 0; j < count; ++j)
        {
            *(cur++) = i;
        }
    }
    std::cout << "count sort with pointers over char array took " << (std::clock() - start) / CLOCKS_PER_SEC << " s" << std::endl;
    delete[] v;
    delete[] table;
}

这给出了大约0.076s

其次,假设我们的值不是整数0-100,我使用以下算法:

对所有100000000个不同的数字进行计数排序(在执行计数排序时,请考虑distribution).

  • Sort numbers.

  • Lookup
  • in this array in this array)。

不幸的是,目前我没有时间来实现和检查,但我相信答案就在那里。

票数 1
EN

Stack Overflow用户

发布于 2016-01-03 17:19:02

下面是上面一些其他用户描述的算法的完整实现。算法的总复杂度为O(n)。

代码语言:javascript
运行
复制
#include <vector>
#include <unordered_map>
#include <algorithm>
#include <cstdint>

void special_sort(std::vector<int>& v, const size_t nExpectedMaxDifferentValues)
{
    typedef int_fast32_t Value;
    typedef size_t Count;
    static_assert(sizeof(Value) >= sizeof(int), "please define Value to int on this platform");

    struct ValHash
    {
        inline std::size_t operator()(const Value k) const
        {
            return k;
        }
    };

    std::unordered_map<Value, Count, ValHash> counts;

    counts.reserve(nExpectedMaxDifferentValues * 100);
    for (const auto x : v)
        ++counts[x];

    std::vector<Value> sorted_numbers;
    sorted_numbers.reserve(counts.size());
    for (const auto& p : counts)
        sorted_numbers.push_back(p.first);

    std::sort(std::begin(sorted_numbers), std::end(sorted_numbers));

    // fill vector with sorted data:
    int* p = v.data();
    for (const auto x : sorted_numbers)
    {
        for (Count i = counts[x]; i > 0; --i)
        {
            *p++ = x;
        }
    }
}

测试速度的主要功能:

代码语言:javascript
运行
复制
#include <random>
#include <limits>
#include <time.h>
#include <iostream>

int main()
{
    std::cout << "Initialize..." << std::endl;
    const size_t N = 100000000;
    const size_t M = 101;

    std::mt19937 gen(5); // use constant to easily reproduce the test
    std::uniform_int_distribution<int> disInt(std::numeric_limits<int>::min(), std::numeric_limits<int>::max());
    std::vector<int> v1;
    v1.reserve(M);

    for (size_t i = 0; i < M; ++i)
        v1.push_back(disInt(gen));

    std::uniform_int_distribution<size_t> disIndex(0, M-1);
    std::vector<int> v2;
    v2.reserve(N);

    for (size_t i = 0; i < N; ++i)
        v2.push_back(v1[disIndex(gen)]);

    std::cout << "Sort..." << std::endl;
    const clock_t begin_time = clock();

    special_sort(v2, M);

    const double seconds = double(clock() - begin_time) / CLOCKS_PER_SEC;
    std::cout << "Sorting took " << int(seconds * 1000) << " ms" << std::endl;
    return 0;
}

我的笔记本电脑的程序输出(由x86_64的MSVC 2013更新5编译,在2.40 CPU的酷睿i7-4700MQ处理器上运行):

代码语言:javascript
运行
复制
Initialize...
Sort...
Sorting took 374 ms

有许多魔术和半魔术优化可以得到这个结果:

  • 使用自己的简单哈希函数:-50%
  • 使用100作为哈希表存储桶计数的乘数:-50%
  • 编译为x64而不是32位代码(x86):-25%
  • 使用C++11 foreach而不是具有迭代器的等效函数:-33%

<代码>F214

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33720312

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档