多线程计数排序

Posted

技术标签:

【中文标题】多线程计数排序【英文标题】:Multi-threaded Counting Sort 【发布时间】:2013-08-16 05:18:34 【问题描述】:

我有一个大学作业,要求我用 Java 中的 n 个线程编写计数排序算法。我们还没有真正得到比这更多的信息。我认为最好的方法是将数组划分为 n 个部分,然后每个线程对一个部分进行排序。问题是我不确定如何正确分区数组;我只看到了如何划分为 2 个部分的示例,而不是 n 个部分。

如果有人可以像我解释的那样向我提供有关如何对其进行分区的逻辑,或者提供一些伪代码,我将不胜感激。请不要源代码,这是我必须做的作业。

我对实际排序没有问题,只是分区。

谢谢。

【问题讨论】:

【参考方案1】:

定义

假设您有一个数组a[0..n-1] 进行排序,并且您想使用k 线程进行排序。

为简单起见,我们假设最小元素的值为 0,最大的元素值为 m。如果最小值不等于 0,那么您可以在将元素分配给线程期间缩放值。

拆分成线程

将您的数组划分为k 块,每个块最多包含floor(m/k) + 1 不同的元素值。

i-th 块由元素 a[j] 组成,这样:

(i - 1) * (floor(m/k) + 1) <= a[j] < i * (floor(m/k) + 1)

例如,如果您有一个包含 10 个元素的数组:

a[0..9] = 1, 2, 5, 0, 3, 7, 2, 3 ,4, 6k = 3,然后是 m = 7,这 3 个块是:

chunk_1: elements in range [0,3) -> [1, 2, 0, 2]
chunk_2: elements in range [3,6) -> [5, 3, 3, 4]
chunk_3: elements in range [6,9) -> [6, 7]

接下来,将每个块分配给一个单独的线程。每个线程对一个块进行排序并让整个数组排序,只需将所有线程的结果按顺序连接起来:

thread_1thread_2...thread_k

复杂性:

如你所知,计数排序的复杂度是O(n + L),其中n是要排序的元素个数,L是元素的最大值。

首先,请注意,您可以按比例缩小每个线程中的值,即该线程中的L < floor(m/k) + 1,因此每个线程中计数排序的复杂性始终取决于该线程中的元素数量。

如果假设值的分布是均匀的,那么每个线程中的预期元素数也是floor(m/k),因此每个线程的总复杂度为O(m/k)

【讨论】:

谢谢,很有帮助。只是一个关于块大小的问题:你说每个块都有 floor(m/k) + 1 个元素。在您的示例中,这将是 3 个元素。但是,您的块有 4。是否有错误? 是的,这是一个错误。现在已经修好了。【参考方案2】:

我想到的第一个想法是递归地对数组进行分区。也就是说,如果你可以分区成 2 ,你也可以分区成 4 ,对吧?

一种更先进和现代的方法是分割成比线程或进程更多的部分。然后将这些部分动态分配给线程。

【讨论】:

我已经尝试过了,但我不确定如何正确分区它们。例如,我有这个数组:37、1、27、11、15、12、34、29、4、10。对其进行分区后,我得到:10,1,4,11,15,12,34,29,27,37(枢轴点是平均值)。我做得对吗? @Mr_Bean:您重新排列了数组而不是分区(至少我不会称之为分区;))。无论如何。将结果视为两个数组:1,4 和 11,15,12,34,29,27,37。枢轴元件10可以添加两个或一个。然后你用新的数组重复这个。还要查找“合并排序”... 哦,好的,谢谢。我看到了一个实现,他们重新排列了数组,使分区大小相同(或减 1)。会试一试。

以上是关于多线程计数排序的主要内容,如果未能解决你的问题,请参考以下文章

计数排序(桶排序)----《程序员小灰》

Sonata Admin Bundle:按计数一对多关系排序

根据对多关系中相关对象的计数对获取请求进行排序

算法渣-排序-计数排序

常用排序算法基数排序桶排序以及计数排序

给定数额买物品最多数量的三种解法(计数排序贪心dp)