Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 将具有重复值的整数数组部分排序到存储桶中的最快方法_C_Arrays_Algorithm_Sorting_Bucket - Fatal编程技术网

C 将具有重复值的整数数组部分排序到存储桶中的最快方法

C 将具有重复值的整数数组部分排序到存储桶中的最快方法,c,arrays,algorithm,sorting,bucket,C,Arrays,Algorithm,Sorting,Bucket,假设我有一个大的未排序整数数组(C/C++),它大部分重复一小部分值。例如,如果我从以下数组开始: { 0, 3, 3, 3, 0, 1, 1, 1, 3, 2, 2, 3, 0, 1, 1, 1, 2, 2, 2, 2, 0, 0, 1} 最后,我想说: { 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3} 实际上,我的数组将有数千个元素,但它们可以拥有的值的范围仍然相对较小,比如十几个可能的值 我的问

假设我有一个大的未排序整数数组(C/C++),它大部分重复一小部分值。例如,如果我从以下数组开始:

{ 0, 3, 3, 3, 0, 1, 1, 1, 3, 2, 2, 3, 0, 1, 1, 1, 2, 2, 2, 2, 0, 0, 1}
最后,我想说:

{ 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3}
实际上,我的数组将有数千个元素,但它们可以拥有的值的范围仍然相对较小,比如十几个可能的值

我的问题是,传统的排序算法(qsort、mergesort等)似乎有点过头了,因为它们会试图确保每个元素都处于正确的位置。但我正在寻找一种算法,该算法只关心将元素分组到“bucket”中,并且知道一旦实现就终止

使用地图:

map<int, unsigned> counts;
for (auto value: values)
    ++counts[value];

auto it = begin(values);
for (auto value_count : counts)
    while (value_count.second--)
        *it++ = value_count.first;
map计数;
用于(自动值:值)
++计数[值];
自动it=开始(值);
用于(自动值\u计数:计数)
while(值\u count.second--)
*it++=值\计数优先;
也就是说,创建值到计数的有序映射,然后使用它覆盖(或在别处创建)每个值的正确计数的整个数组

当然,如果值始终是小范围内的整数,则可以使用数组而不是映射,例如[0,3]中的值:

array<unsigned, 4> counts = {};
for (auto value: values)
    ++counts[value];
数组计数={};
用于(自动值:值)
++计数[值];
基于此:

大部分重复小范围值的未排序整数数组

假设列表中有一个最大值,可以执行以下操作:

#include <stdio.h>
#include <string.h>

int group_vals(int *arr, size_t len, int max)
{
    int count[max+1];
    memset(count, 0, sizeof count);


    for(size_t i = 0; i < len; ++i)
        count[arr[i]]++;

    size_t index = 0;
    for(size_t i = 0; i < max + 1; ++i)
    {
        for(size_t j = 0; j < count[i]; ++j)
            arr[index++] = i;
    }
}

int main(void)
{
    int arr[] = { 0, 3, 3, 3, 0, 1, 1, 1, 3, 2, 2, 3, 0, 1, 1, 1, 2, 2, 2, 2, 0, 0, 1};

    for(size_t i = 0; i < sizeof arr / sizeof *arr; ++i)
        printf("%d, ", arr[i]);
    puts("");

    group_vals(arr, sizeof arr / sizeof *arr, 3);

    for(size_t i = 0; i < sizeof arr / sizeof *arr; ++i)
        printf("%d, ", arr[i]);
    puts("");

    return 0;
}
编辑

注意:正如用户在评论中指出的,这种方法的局限性 它只在原始数组仅包含正数时才起作用。 改进it以处理负数不是什么大问题:

int group_vals(int *arr, size_t len, int absmax)
{
    int count[2*absmax+1];
    memset(count, 0, sizeof count);


    for(size_t i = 0; i < len; ++i)
    {
        int v = arr[i];
        size_t idx;

        if(v == 0)
            idx = absmax;
        else
            idx = absmax + v;

        count[idx]++;
    }

    size_t index = 0;
    for(size_t i = 0; i < 2*absmax + 1; ++i)
    {
        int v;
        if(i == absmax)
            v = 0;
            v = i - absmax;

        for(size_t j = 0; j < count[i]; ++j)
        {
            arr[index++] = v;
        }
    }
}
PS:我没有读约翰·兹温克的答案,但我们都有相同的想法,这是
C版本,

C还是C++?另外:“传统的排序算法(qsort、mergesort等)似乎有点过头了”,怎么会呢?它们跑得不够快,还是有什么问题?@BaummitAugen我可以选择在这里使用。他们跑得不够快是问题所在,我需要一些可以提前终止的东西。我不需要有人为我实现整个算法,只需要一个指向对我的情况有用的东西的正确方向的指针。那么请做出选择。不同的语言会产生不同的解决方案。传统的排序算法看起来有点过分了为什么?你有一个排序问题,他们就是这样做的。我不想对元素进行计数,而是将它们部分地排序到桶中。@Sunny724这里的计数用作排序机制。由于您有许多重复项,因此计算每个重复项的数量可以被认为是将每个值放入自己的桶中。由于每个bucket中的值相同,您只需跟踪bucket中有多少项,然后写出整个排序数组。这是一个好主意,因为它实际上在不丢失数据的情况下减少了数据占用。回答..+1,但这不是一个
C
问题吗?标签上写着so@coderredoc当Neil Butterworth删除某个点的两个标签时,约翰最初已经标注了C++和C++。然后,OP在评论(问题)中说他/她想要一个C语言的解决方案,所以我再次阅读了C标签。@JohnZwinck说我和你有相同的想法,但我写了一个C语言的解决方案。我要确保你提到你还假设所有数组元素都是非负的。这是发布的两个解决方案之间的差异。@coderredoc感谢您的反馈,我没有考虑负数,我更新了我的答案。
-2, 0, 1, 3, 2, 3, -2, -1, -1, 3, 3, 
-2, -2, -1, -1, 0, 1, 2, 3, 3, 3, 3,