Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.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
Algorithm 有效地合并许多未排序的列表_Algorithm_Parallel Processing - Fatal编程技术网

Algorithm 有效地合并许多未排序的列表

Algorithm 有效地合并许多未排序的列表,algorithm,parallel-processing,Algorithm,Parallel Processing,我有许多巨大的未排序的列表包含(用户、金额)元组。每个列表对应一天。 现在我想把所有的列表合并成一个列表,其中包含给定用户的累积值。我有两种方法: 方法1:对单个列表进行排序,然后迭代使用合并排序 方法2:形成一个以用户为键的HashMap,然后遍历列表 并更新键的值(如果存在),或添加一个具有值的新键 如果存在m列表,并且每个列表可能具有不同的长度(k1,k2,…,km) 问题: 哪个是有效的解决方案? 哪个解决方案可以在多个线程中运行? 还是有更好的解决办法 示例: 第1天:(用户110

我有许多巨大的未排序的
列表
包含
(用户、金额)
元组。每个列表对应一天。 现在我想把所有的列表合并成一个列表,其中包含给定用户的累积值。我有两种方法:

  • 方法1:对单个列表进行排序,然后迭代使用合并排序

  • 方法2:形成一个以用户为键的HashMap,然后遍历列表 并更新键的值(如果存在),或添加一个具有值的新键

如果存在
m
列表,并且每个列表可能具有不同的长度
(k1,k2,…,km)

问题:

哪个是有效的解决方案?
哪个解决方案可以在多个线程中运行?
还是有更好的解决办法

示例:

第1天:(用户1100),(用户2200)
第二天:(用户2,10)、(用户1100)、(用户3,10)

合并后的列表:(user1200),(user2210),(user3,10)

排序和解决方案的复杂性为O(mn log n)+O(n log m),其中m是假设每个列表大小为n的列表数


为了计算基于散列的解决方案的复杂性,假设有k个用户。将k元素插入
HashMap
(Java)或
map
(C++)的操作取O(k log k)。在最佳情况下更改mn-k值取(mn-k)O(1),在最坏情况下更改mn-k值取(mn-k)O(log k)。总体复杂度为O(mn log k)。因此,在这两种方法中,哈希似乎更好,特别是当k远小于mn时。

HashMap方法更好,因为它是O(N)。这两种解决方案都可以在多个线程中运行,但需要进行不同的修改以支持并发性

1总体方法和复杂性

我想:

  • 客户端数量较大,但有限=N
  • 持续增长的天数=M
  • 也许每一天,我们都有每一位客户(或者几乎是这样)
将工作的复杂性降至最低:

  • 处理每个数据,以便执行M.N操作。由于您不想为求和保留元素,因此只需执行以下操作: 部分和+新值,所以,一切都需要M.N x有限时间(我想你没有几十亿美元)

  • 您必须在N个客户机上生成数据(对于每个数据,您必须在每个客户机上查找、求和、存储……)。 对我来说,最短的时间是至少对客户机进行一次排序(或使用任何方法对其进行索引), 所以,时间就是O(N logn),用最好的算法和 实现(也有更快的方法,但空间非常大)

所以,至少需要O(N logn)+O(M.N)

2种可能的解决方案:

您的方法1浪费时间:因为您对每个列表进行排序(使用相同的数据)。 你需要M.O(N logn)+O(M.N)。 您只需要一次排序(之后才能求和)

您的方法2是最短的方法。

3如何并行化?

您(至少)有两种方法可以分割数据:使用天数,或使用客户端。因为您想在客户机上求和,所以使用 第二个

您的流程易于扩展。

然后,您可以使用一个简单的哈希函数(客户端的第一个或最后一个字符,或者非常简单的东西) =>每个线程(或进程或计算机)接收每个数据,并仅为其客户端保留数据

您可以像这样拆分每个作业(处理、求和、检索等)

If将花费几乎相同的总时间:

使用k进程,您将拥有k.O(N/k log N/k)+k*Ox(M.N)+k.O(M.N/k)

当你分N/k赢的时候,你通过选择(牛,我想很快)

然后您可以在许多独立的机器上分配作业。


希望能有所帮助。

看起来是一个理想的问题,因为HashMap方法更好,因为它是O(N)刚刚注意到任务描述中缺少一件非常重要的事情:每个给定列表中的键/用户是否唯一?对于在<代码> java中使用关键字保存的值更新,UTI.MAP<代码>,我想考虑。方法1不等于任何东西。在合并排序的方法之一中,如果用户是相同的,则需要添加值。错误…不对。。错。。。。在哈希表中插入和更新项是O(1)。在C++中,它是无序的,在java中是HashMap。将所有元素插入哈希将是O(N),其中N是所有列表中的项目总数(这不完全是mn,因为列表大小不同)。此外,将m个列表与N个项目合并将花费O(N log m)时间。@灰胡子是的,每个用户将有一个值,因此每个用户有一对。对数并不意味着总是O(n logn)(例如,二进制搜索有O(logn))。请再次检查并让我知道。@gen-y-s请查找HashMap和map是如何实现的,您会发现它们实际上是树。因此,对数插入时间。即使列表大小不同,为什么要将所有元素插入HashMap??这就是为什么我提到要插入一些k,0=mN个元素,如何在O(N logm)时间内完成?我很想了解这个方法。@Erobrere HashMap是一个哈希表,TreeMap是一个二进制搜索树。在你告诉任何人去查任何东西之前,你最好自己查一下。顺便说一句,Map只是一个接口,实现是HashMap和TreeMap。使用方法一,通过让线程池合并两个列表并放回队列,可以很容易地实现并发。但是我不确定如何使用hashmap?对于第二种方法,您可以使用线程,方法是让每个线程获取队列中的下一个列表并处理它,并相应地更新哈希表(哈希表访问应该在bucket级别同步)。答案太棒了!如果客户端列表已经存在,该怎么办