【问题标题】:merge in-place without external storage无需外部存储就地合并
【发布时间】:2012-03-10 17:13:12
【问题描述】:

我想将两个具有排序值的数组合并为一个。由于两个源数组都存储为大型数组的后续部分,我想知道您是否知道将它们合并到大型存储中的方法。意思是就地合并。

我找到的所有方法都需要一些外部存储。它们通常需要 sqrt(n) 临时数组。没有它有没有有效的方法?

我正在使用 C#。也欢迎其他语言。提前致谢!

【问题讨论】:

  • this 呢?
  • 这个问题已经在这里问过好几次了。你先尝试搜索了吗?
  • 似乎与以下内容重复:stackoverflow.com/q/4373307/650084
  • 如果值存储为较大数组的后续部分,您只需对数组进行排序,然后删除相等的连续值。
  • 感谢您的链接! @ben 对排序后的数组进行排序太昂贵了。

标签: c# arrays merge in-place


【解决方案1】:

AFAIK,如果不显着增加必要的比较次数和元素移动次数,则合并两个(甚至排序的)数组无法就地工作。请参阅:merge sort。但是,存在阻塞的变体,它们能够通过使用长度为 sqrt(n) 的临时数组对长度为 n 的列表进行排序 - 正如您所写 - 通过仍然保持操作数量相当低。它还不错 - 但它也不是“什么都没有”,显然是你能得到的最好的。

对于实际情况,如果您负担得起,您最好使用临时数组来合并您的列表。

【讨论】:

    【解决方案2】:

    如果值存储为较大数组的后续部分,您只需对数组进行排序,然后删除相等的连续值。

    void  SortAndDedupe(Array<T> a)
    {
        // Do an efficient in-place sort
        a.Sort();
        // Now deduplicate
        int lwm = 0; // low water mark
        int hwm = 1; // High water mark
        while(hwm < a.length)
        {
            // If the lwm and hwm elements are the same, it is a duplicate entry.
            if(a[lwm] == a[hwm])
            {
                hwm++;
            }else{
                // Not a duplicate entry - move the lwm up
                // and copy down the hwm element over the gap.
                lwm++;
                if(lwm < hwm){
                    a[lwm] = a[hwm];
                }
                hwm++;
            }
        }
        // New length is lwm
        // number of elements removed is (hwm-lwm-1)
    }
    

    在您断定这将太慢之前,请实施并分析它。这大约需要十分钟。

    编辑:这当然可以通过使用不同的排序而不是内置排序来改进,例如Quicksort、Heapsort 或 Smoothsort,具体取决于哪个在实践中提供更好的性能。请注意,硬件架构问题意味着实际的性能比较很可能与大 O 分析的结果大相径庭。

    您确实需要在您的实际硬件/操作系统平台上使用不同的排序算法对其进行分析。

    注意:我不是在试图给出一个学术答案,我试图给出一个实用的答案,假设你正在尝试解决一个真正的问题。

    【讨论】:

    • 非常感谢本。但在我使用探查器之前,我需要指出,排序不会将源的排序状态纳入帐户。因此它将花费常规的 O(n log n)。我希望在您的重复数据删除范围内得到一些东西,关于工作量,即 O(n)。
    • 感谢您的编辑。我坚持大 O 的重要性,因为我们只需要处理大量数据。如您所知,对于大数据,O 表示法确实对应于执行速度。同样的原因,为什么我需要就地。大型外部存储会导致 gc 更多的工作。
    • 即使是大数据大O也不一定对应性能。它不仅取决于比较与交换的相对费用,还取决于内存位置等硬件问题,包括分页和处理器缓存使用。您最好编写三个或四个版本并比较它们的性能。特别是如果您出于理论而非经验原因而关注归并排序的存储要求 --- 只要尝试一下,您就会知道问题是否真实存在!请告诉我们您的发现 - 我对您的结果非常感兴趣。
    • 我感谢你的努力,本。但这根本不能回答问题。我实际上正在寻找第三种解决方案来实施和测试。如果它存在,它很可能会胜过其他人。否定这一点也会否定在该研究主题上花费的努力。但也许它根本不存在。我会在剩下的比之间做出选择。
    • @AnastasiaRushda 我确实理解大 O 亲和力。但是关于您对临时存储的担忧,我建议您只是重复使用该存储?合并的解决方案根本不需要 GC!?这使实现保持干净和可维护。
    【解决方案3】:

    不关心外部存储。 sqrt(n) 甚至更大应该不会损害您的性能。您只需要确保存储是池化的。尤其是对于大数据。特别是在循环中合并它们。否则,GC 将承受压力并占用相当一部分的 CPU 时间/内存带宽。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-01-28
      • 2020-12-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-06
      • 1970-01-01
      • 2011-04-01
      相关资源
      最近更新 更多