我有一个大学作业,要求我用Java 中的n 个线程编写计数排序算法。我们还没有真正得到比这更多的信息。我认为最好的方法是将数组划分为n 个部分,然后每个线程对一个部分进行排序。问题是我不确定如何正确分区数组;我只看到了如何划分为 2 个部分的示例,而不是n 个部分。
如果有人可以像我解释的那样向我提供有关如何对其进行分区的逻辑,或者提供一些伪代码,我将不胜感激。请不要源代码,这是我必须做的作业。
我对实际排序没有问题,只是分区。
谢谢。
假设您有一个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, 6}
和k = 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_1
thread_2
...
thread_k
如您所知,计数排序的复杂性是O(n + L)
要n
排序的元素个数,并且L
是元素的最大值。
首先,请注意,您可以按比例缩小每个线程中的值,即L < floor(m/k) + 1
在该线程中,因此每个线程中计数排序的复杂性始终取决于该线程中的元素数量。
如果假设值的分布是均匀的,那么每个线程中的预期元素数也是floor(m/k)
如此,因此每个线程的总复杂度为O(m/k)
.
我想到的第一个想法是递归地对数组进行分区。这意味着如果你可以分区成 2 ,你也可以分区成 4 ,对吧?
一种更先进、更现代的方法是分割成比线程或进程更多的部分。然后将这些部分动态分配给线程。