简体   繁体   English

运行时错误:在 C++ 中合并两个排序的 arrays

[英]Runtime Error: merge two sorted arrays in C++

I wrote this piece of code for merging two sorted arrays:-我编写了这段代码用于合并两个排序的 arrays:-

   class Solution {
   public:
     void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
         int p1=m-1, p2=n-1, i=m+n-1;      
         while(p2>=0){
     
        if(p1>=0 && nums1[p1]<nums2[p2]){
            
            nums1[i]=nums2[p2];
            p2--;
            
        }//if
        else{
             nums1[i]=nums1[p1];
            p1--;
        }
        i--;
    }
    
}//fn
};

This is throwing up a runtime error.这引发了运行时错误。 Can someone help me resolve this?有人可以帮我解决这个问题吗?

I put OPs sample into an MCVE on coliru and was able to reproduce the issue of OP.我将 OP 样本放入coliru上的MCVE中,并能够重现 OP 的问题。 In my case, the execution simply was aborted due to an out-of-bounds access.就我而言,执行只是由于越界访问而中止。

I highly suspect that OP passed in the nums1, nums1.size(), nums2, nums2.size() into Solution::merge() .我高度怀疑 OP 将nums1, nums1.size(), nums2, nums2.size()到了Solution::merge()中。 As the merge is destructive (writes result into one of the input containers), this has to be considered.由于合并是破坏性的(将结果写入输入容器之一),因此必须考虑这一点。

IMHO, OP seems to be aware of this basically as the merge is done from back to front.恕我直言,OP似乎基本上意识到了这一点,因为合并是从后到前完成的。

However, as nums1 is used for output it has to be provided with sufficient size before merging.但是,由于nums1用于 output,因此必须在合并之前为其提供足够的大小。

Eg nums1.resize(m + n);例如nums1.resize(m + n); at the begin of merge will do the job.在合并开始时将完成这项工作。

My MCVE with fix:我的 MCVE 修复:

#include <iostream>
#include <vector>

class Solution {
    
  public:
  
    void merge(std::vector<int>& nums1, int m, std::vector<int>& nums2, int n)
    {
      nums1.resize(m + n); // <= ENSURE SUFFICIENT STORAGE IN nums1
      int p1 = m - 1, p2 = n - 1, i = m + n - 1;      
      while (p2 >= 0) {
        if (p1 >= 0 && nums1[p1] < nums2[p2]) {
          nums1[i] = nums2[p2];
          p2--;
        } else {
          nums1[i] = nums1[p1];
          p1--;
        }
        i--;
      }
    }
};

int main()
{
  // sample data
  std::vector<int> nums1{ 1, 3, 5, 7, 9 };
  std::vector<int> nums2{ 2, 4, 6, 8 };
  // run merge
  Solution().merge(nums1, (int)nums1.size(), nums2, (int)nums2.size());
  // output result
  std::cout << "nums1: {";
  const char* sep = " ";
  for (const int num : nums1) {
    std::cout << sep << num;
    sep = ", ";
  }
  std::cout << " }" << std::endl;
}

Output: Output:

nums1: { 1, 2, 3, 4, 5, 6, 7, 8, 9 }

Live Demo on colirucoliru 现场演示


@Armin Montigny recommended the use of std::merge() instead of a hand-knitted implementation. @Armin Montigny建议使用std::merge()而不是手工编织的实现。

First I had some doubts whether it's able to manage destructive merging as well but after thinking twice I realized that it will do it perfectly if used right.首先,我怀疑它是否也能够管理破坏性合并,但经过深思熟虑后,我意识到如果使用得当,它会完美地做到这一点。 I modified my MCVE to see how this would look like.我修改了我的 MCVE 以查看它的外观。

My alternative MCVE using std::merge() :我使用std::merge()的替代 MCVE :

#include <algorithm>
#include <functional>
#include <iostream>
#include <vector>

class Solution {
    
  public:
  
    void merge(std::vector<int>& nums1, int m, std::vector<int>& nums2, int n)
    {
      nums1.resize(m + n); // <= ENSURE SUFFICIENT STORAGE IN nums1
      std::merge(
        nums1.rbegin() + n, nums1.rend(), // consider that nums1 is already resized
        nums2.rbegin(), nums2.rend(),
        nums1.rbegin(),
        std::greater<int>());
    }
};

int main()
{
  // sample data
  std::vector<int> nums1{ 1, 3, 5, 7, 9 };
  std::vector<int> nums2{ 2, 4, 6, 8 };
  // run merge
  Solution().merge(nums1, (int)nums1.size(), nums2, (int)nums2.size());
  // output result
  std::cout << "nums1: {";
  const char* sep = " ";
  for (const int num : nums1) {
    std::cout << sep << num;
    sep = ", ";
  }
  std::cout << " }" << std::endl;
}

Output: Output:

nums1: { 1, 2, 3, 4, 5, 6, 7, 8, 9 }

Live Demo on colirucoliru 现场演示

Notes:笔记:

  1. I used rbegin() and rend() , to merge the vectors from end to begin, like OP did it.我使用rbegin()rend()来从头到尾合并向量,就像 OP 那样。 This is necessary to write merged elements always after where the still unprocessed elements have to be read.这对于始终在必须读取仍未处理的元素之后写入合并元素是必要的。
  2. The input iterators for nums1 may look a bit surprising on the 1 st glance. nums1的输入迭代器乍一看可能有点令人惊讶。 Using nums1.rbegin() + n is necessary to address to skip the space which was already allocated to store the additional elements of nums2 .必须使用nums1.rbegin() + n来跳过已分配用于存储nums2附加元素的空间。 (That are exactly n .) (那正是n 。)
  3. The std::merge() has to be used with a custom predicate (eg std::greater ) as I used ascending ordered sample data but merge from back to front which reverses that into a descending order . std::merge()必须与自定义谓词(例如std::greater )一起使用,因为我使用升序排序的样本数据,但从后到前合并,将其反转为降序

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM