使用没有第三个数组的递归合并两个排序数组

Posted

技术标签:

【中文标题】使用没有第三个数组的递归合并两个排序数组【英文标题】:Merge two sorted arrays with recursion without 3nd array 【发布时间】:2022-01-16 08:57:48 【问题描述】:

我是一年级计算机科学专业的学生。 我被赋予了递归任务。 我需要编写一个递归函数来获取两个数组,它们是它们的物理大小(非负数),并对数组进行排序并以排序方式将它们放入第二个数组中,而无需设置数组来寻求帮助。大概第二个数组的大小就足够了。我无法编写适合我的代码,我希望你能帮助我。

【问题讨论】:

数组是否已排序?因为在标题中你写了“合并两个排序的数组”,但在描述中你写的函数应该对数组进行排序。 "得到两个数组" 怎么样?函数的接口是什么?它在哪里可以访问它们? “它们是它们的物理大小”尚不清楚。界面是否提供这些尺寸? “想必第二个数组的大小就足够了。” 好。但是你需要三个大小,数组 1,数组 2 中要排序的条目以及数组的总大小。或者保证数组 2 可以取所有,并且仍然是要排序的条目的数量。您需要提供minimal reproducible example 来定义接口。然后,您可以获得实施方面的帮助。考虑引用整个家庭作业。 你仍然应该展示你自己的努力。否则... 所有“不知道如何开始”问题的答案是:“阅读、查找工作示例、尝试、修复、重做”。 IE。阅读一些教科书或教程,找到一个 HelloWorld 或示例代码,尝试朝着你的目标小步改变它,测试,调试;然后尝试下一次迭代。根据How to Ask 并可能使用此处描述的折衷方案:meta.***.com/questions/334822/…跨度> 【参考方案1】:

所以你有两个排序数组,我们假设第二个数组分配了额外的空间来保存合并后的数组。

这是记忆中的样子:

array0, length 4
+-------+
|a|b|d|h|
+0-1-2-3+

array1, length 3
+-------------+
|b|c|e| | | | |
+0-1-2-3-4-5-6+

多余的空间在array1的存储空间的末尾。

合并数组后,array1 的索引 6 处的值是多少?由于索引 6 将是合并数组中的最后一个元素,因此它将是任一输入数组的最大元素。由于输入数组已经排序,它将是array0 的最后一个元素或array1 的最后一个元素。让我们比较它们并将较大的元素复制到索引 6。由于 h 大于 e,我们将 h 复制到索引 6。由于我们现在将 array0 的最后一个元素放在其最终位置,我们可以假装array0 现在长度为 3。

array0, length 3
+-------+
|a|b|d| |
+0-1-2-3+

array1, length 3
+-------------+
|b|c|e| | | |h|
+0-1-2-3-4-5-6+

现在我们对 array1 的索引 5 再次执行相同的操作。我们比较(缩短的)array0array1 的最后一个元素。由于e 大于d,我们将e 复制到索引5 并将array1 的长度减少1:

array0, length 3
+-------+
|a|b|d| |
+0-1-2-3+

array1, length 2
+-------------+
|b|c| | | |e|h|
+0-1-2-3-4-5-6+

重复直到输入数组被缩短到长度为 0,array1 的存储将被最终合并的数组填充。

【讨论】:

【参考方案2】:

这是之前建议的工作代码。 如果您知道如何使其成为二进制文件,我想在这里提出您的建议。

void combineArrays(int sortedArr1[], int size1,
    int sortedArr2[], int size2)

    int combinedSizes = size1 + size2;
    if (size1 == 0);
    else if (sortedArr1[size1 - 1] > sortedArr2[size2 - 1])
    
        sortedArr2[size2+size1-1] = sortedArr1[size1 - 1];
        combineArrays(sortedArr1, size1 - 1, sortedArr2, size2);
    
    else//sortedArr1[size1 - 1] < sortedArr2[size2 - 1]
    
        sortedArr2[size2 + size1 - 1] = sortedArr2[size2 - 1];
        combineArrays(sortedArr1, size1, sortedArr2, size2 - 1);
    

【讨论】:

combinedSizes 未使用。 if (size1 == 0); else ... 不优雅。 如果size2 == 0 怎么办? if (sortedArr1[size1 - 1] &gt; sortedArr2[size2 - 1]) 会有未定义的行为。【参考方案3】:

假设数组不重叠,您可以从最高索引开始合并已排序的数组:

void mergeArrays(const int * restrict a1, size_t n1,
                 int * restrict a2, size_t n2)

    for (size_t k = n1 + n2; n1 > 0;) 
        if (n2 == 0 || a1[n1 - 1] > a2[n2 - 1]) 
            a2[--k] = a1[--n1];
         else 
            a2[--k] = a2[--n2];
        
    

这可以简化为:

void mergeArrays(const int * restrict a1, size_t n1,
                 int * restrict a2, size_t n2)

    for (size_t k = n1 + n2; n1 > 0;)
        a2[--k] = (n2 == 0 || a1[n1 - 1] > a2[n2 - 1]) ? a1[--n1] : a2[--n2];

如果需要使用递归,将循环改为递归调用:

void mergeArrays(const int * restrict a1, size_t n1,
                 int * restrict a2, size_t n2)

    if (n1 > 0) 
        if (n2 == 0 || a1[n1 - 1] > a2[n2 - 1]) 
            a2[n1 + n2 - 1] = a1[n1 - 1];
            mergeArrays(a1, n1 - 1, a2, n2);
         else 
            a2[n1 + n2 - 1] = a2[n2 - 1];
            mergeArrays(a1, n1, a2, n2 - 1);
        
    

【讨论】:

以上是关于使用没有第三个数组的递归合并两个排序数组的主要内容,如果未能解决你的问题,请参考以下文章

链表:合并两个有序的链表

PHP快速排序算法

15-21. 合并两个有序数组(第二次遇到,却没有想起用递归,再总结一次)

归并排序

归并排序

算法4 整理