C++ 如何组合2个部分排序的数组?

C++ 如何组合2个部分排序的数组?,c++,algorithm,search,sorting,data-structures,C++,Algorithm,Search,Sorting,Data Structures,给出了两个具有int、A1和A2的数组。A1长度为L1,A2长度为L1+L2。 A1和A2的前L2元素已排序。将第一个L2元素组合成A2。 e、 g 我的解决方案: 通过将min{A1[i],A2[i]}放入数组B[i],O(2*L2)来拾取每个元素 复制B到A2。O(L1+L2) 不应更改未分类的零件 有更好的解决办法吗 谢谢 将A1和A2复制到一个阵列中 std::就地_与begin、begin+L2、end合并 (您没有指定任何库函数!);) 这听起来像是一个家庭作业问题,在提供家庭作业代

给出了两个具有int、A1和A2的数组。A1长度为L1,A2长度为L1+L2。 A1和A2的前L2元素已排序。将第一个L2元素组合成A2。 e、 g

我的解决方案:

通过将min{A1[i],A2[i]}放入数组B[i],O(2*L2)来拾取每个元素 复制B到A2。O(L1+L2)

不应更改未分类的零件

有更好的解决办法吗

谢谢

  • 将A1和A2复制到一个阵列中
  • std::就地_与begin、begin+L2、end合并
  • (您没有指定任何库函数!);)

    这听起来像是一个家庭作业问题,在提供家庭作业代码之前,我通常会犹豫。但是,这里似乎需要一个示例:

    std::vector<int> A1; // initialize to { 1  3  6  0 }
    std::vector<int> A2; // initialize to { 2  5  7  13  10 22 11 }
    
    // Now assumption here is that we want L2 items from A1, so let's copy
    A2.insert(A2.begin(), A1.begin(), A1.begin() + L2);
    
    // Now A2 contains the sorted range from A1 0 is dropped (?)
    // Now call inplace_merge, this leaves the unsorted segment of A2 alone, and only includes
    // L2 items from A2.
    std::inplace_merge(A2.begin(), A2.begin() + L2, A2.begin() + (2*L2));
    
    std::vector A1;//初始化为{1 3 6 0}
    std::矢量A2;//初始化为{2 5 7 13 10 22 11}
    //现在假设我们想要A1中的L2项,所以让我们复制
    A2.插入(A2.begin(),A1.begin(),A1.begin()+L2);
    //现在A2包含从A1 0开始的排序范围(?)
    //现在调用inplace_merge,这样就只剩下A2的未排序段,并且只包括
    //A2中的L2项。
    std::inplace_merge(A2.begin(),A2.begin()+L2,A2.begin()+(2*L2));
    
    现在我已经知道了什么是
    L1
    L2

    {
        std::vector<int> B(L2+L2+L1, 0);
        std::merge(A1.begin(), A1.begin()+L2, A2.begin(), A2.begin()+L2, B.begin());
        if (L1 > L2)
            B.insert(B.end(), A2.begin()+L2, A2.end());
        A2.swap(B);
    }
    
    {
    std::向量B(L2+L2+L1,0);
    合并(A1.begin(),A1.begin()+L2,A2.begin(),A2.begin()+L2,B.begin());
    如果(L1>L2)
    B.插入(B.结束(),A2.开始()+L2,A2.结束());
    A2.互换(B);
    }
    
    B包含[合并的已排序部分][未排序的A2]。那是正确的格式吗?这是你发布的算法。就地(如Nim)速度较慢,但占用的内存较少,因此这是一个折衷方案

    int* semiMerge(int*, int, int*, int);
    
    int main() {
      const int A1[] = {1, 3, 6, 0};
      const int A2[] = {2, 5, 7, 13, 10, 22, 11};
    
      const int L1 = sizeof(A1)/sizeof(int);
      const int L2 = sizeof(A2)/sizeof(int) - L1;
    
      int* out = semiMerge(A1, L1, A2, L2);
    }
    
    int* semiMerge(A1, L1, A2, L2) {
      int* output = new int[L2 + L2 + L1];
    
      //merge does a sorted combination of the items--both sets must be sorted up to the endpoints;
      //we want to merge only the first L1 results from each array
      std::merge(A1, A1 + L2,
                 A2, A2 + L2,
                 output);
      //at this point, we have an array of 2*L1 elements, all sorted properly.
    
    
      //we want to start looking at the first element we didn't copy from A2,
      //the -1 is to account for the fact that begin() + L1 is the start of the L1+1th slot
      std::copy(A2 + L2,
                A2 + L2 + L1, 
                (output + L2 + L2 - 1));
    
    return output;
    }
    

    我选择将A1和A1显示为静态数组,但是如果您将它们作为
    int*
    s来堆分配的数组,并且如果将完成的数组放置在L2中很重要,那么您可以说
    delete[]L2;L2=输出semiMerge()
    后的code>。我主要选择不这样做,因为我将
    A2
    表示为一个静态数组,而将其切换为
    out
    的内容需要它是一个指向动态数组的指针。

    它是(2*L2*lg 2*L2)。当L2>>L1时,它没有效率。
    合并(开始(A1)、结束(A1)、开始(A2)、结束(A2)、返回插入器(dest))有什么问题?@mooing,是的,如果B可以是一个单独的数组,如果A2(或A1)对这两个数组都足够,那么inplace就更好了,我想……在这种情况下inplace就更好了,end就是两个排序范围的末尾。这将使未排序的部分不受影响。我将再次检查NlogN声明…A2的一部分已排序,另一部分未排序,它们应保持此状态。为什么这些部件没有保存在不同的阵列中?这将简化一切,并提供O(2*L2)。好吧,我尝试了一些想法,但没有一个考虑到你的价值观几乎是有序的。我的直觉告诉我,你应该可以稍微好一点,但不会太多。即使是桶排序也会丢掉预排序的大部分优势。但仍在考虑……通过“将第一个L2元素组合成A2”,你的意思是“第一个L1+L2元素”?看起来是这样的,因为你将A2.length定义为L1+L2,L2将是一个重要的数字,因为你想保留最后的L2数字并附加它们。A2大小将是L2+L2+L1(排序+未排序)。A1结尾的尾随0是什么?完成了你的方法并确保没有内存泄漏。@AndréCaron uh,也许我遗漏了什么,但我看到的唯一变化是您将输出更改为
    std::vector
    ,这是因为您没有更改存储在其中的变量的类型,只是破坏了代码。。。只要客户端记得调用
    delete[]
    @mathias,直接对动态int数组进行操作是有效的:反之亦然。我更改了
    输出
    变量的类型,而不是函数的返回类型。您前面的示例无效,因为(1)它试图从单个
    int*
    参数构造一个向量,(2)它总是泄漏分配的内存,因为指向它的唯一指针位于局部变量中。@mathias:我没有注意到函数的前向声明和
    main()
    我们希望
    int*
    作为输出。接得好!是的,我最初是用vector实现它的,但是我决定把它降到
    int*
    ,因为OP讨论的是处理数组。你抓住了我错过的一部分,做了与我本该做的相反的事。此外,您确实返回了指向数组的指针,客户机有责任在此时管理它。不过,我确实在最下面的一段中使用了错误的
    delete
    ;我已经改变了。
    int* semiMerge(int*, int, int*, int);
    
    int main() {
      const int A1[] = {1, 3, 6, 0};
      const int A2[] = {2, 5, 7, 13, 10, 22, 11};
    
      const int L1 = sizeof(A1)/sizeof(int);
      const int L2 = sizeof(A2)/sizeof(int) - L1;
    
      int* out = semiMerge(A1, L1, A2, L2);
    }
    
    int* semiMerge(A1, L1, A2, L2) {
      int* output = new int[L2 + L2 + L1];
    
      //merge does a sorted combination of the items--both sets must be sorted up to the endpoints;
      //we want to merge only the first L1 results from each array
      std::merge(A1, A1 + L2,
                 A2, A2 + L2,
                 output);
      //at this point, we have an array of 2*L1 elements, all sorted properly.
    
    
      //we want to start looking at the first element we didn't copy from A2,
      //the -1 is to account for the fact that begin() + L1 is the start of the L1+1th slot
      std::copy(A2 + L2,
                A2 + L2 + L1, 
                (output + L2 + L2 - 1));
    
    return output;
    }