Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
122 views
in Technique[技术] by (71.8m points)

How I can merge two 2D arrays according to row in c++

I am facing a problem where two 2-dimensional arrays need to merge according to the given condition, where n=5 and k=3.

1st array->

1 2 
3 4 
5 6 
7 8 
9 10

2nd array->

11 12 13 
14 15 16 
17 18 19 
20 21 22 
23 24 25

The resultant array->

 1 2 11 12 13 
 3 4 14 15 16 
 5 6 17 18 19
 7 8 20 21 22
 9 10 23 24 25

My approach to this problem is to first take an empty 2-D array of above two array dimensions, then to place two array elements into the ans array index by index. I can put the 1st array into ans array, but failed to put the 2nd array into the resultant array. It's showing a run-time error for inserting the 2nd array. I need help for that.

#include <iostream>
using namespace std;

int main()
{
    int n, k;
    cin >> n >> k;
    int p = n - k + 1, q = n - k;
    int a[n + 1][q + 1], b[n + 1][p + 1], ans[n + 1][n + 1];
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= q; ++j)
            a[i][j] = 0;
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= p; ++j)
            b[i][j] = 0;
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= n; ++j)
            ans[i][j] = 0;

    int x = 1;
    for (int i = 1; i <= n; ++i)
    {
        for (int j = 1; j <= q; ++j)
            a[i][j] = x++;
    }
    for (int i = 1; i <= n; ++i)
    {
        for (int j = 1; j <= p; ++j)
            b[i][j] = x++;
    }
    for (int i = 1; i <= n; ++i)
    {
        for (int j = 1; j <= q; ++j)
            ans[i][j] = a[i][j];
    }
    int I = 1, J = 0;
    for (int i = 1; i <= n; ++i)
    {
        I += 2, J++;
        for (int j = 1; j <= p; ++j)
        {
            ans[I][J] = b[i][j];
            I++;
        }
    }
    for (int i = 1; i <= n; ++i)
    {
        for (int j = 1; j <= q; ++j)
            cout << a[i][j] << " ";
        cout << endl;
    }
    for (int i = 1; i <= n; ++i)
    {
        for (int j = 1; j <= p; ++j)
            cout << b[i][j] << " ";
        cout << endl;
    }
    for (int i = 1; i <= n; ++i)
    {
        for (int j = 1; j <= n; ++j)
            cout << ans[i][j] << " ";
        cout << endl;
    }

    return 0;
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

There are three main issues in the posted code

  • a, b and ans are declared as variable length arrays (their sizes aren't known at compile time), a non-standard extension provided by some compilers. The OP could have used a standard container like std::vector or a user-defined class.

  • All the loops start at 1, while in C++ array indices are 0-based. The writer of this code seems to know this fact, but for some reason preferred to allocate extra (unused) space in all the arrays and to accomodate the termitation conditions accordingly.

  • The nested loop which tries to copy the values from b to ans is simply wrong and causes multiple accesses out of bounds.

    int I = 1, J = 0;                     // --->  I = 0, keeping OP's convention
    for (int i = 1; i <= n; ++i)
    {
        I += 2, J++;                      // --->  ++I, J = q
        for (int j = 1; j <= p; ++j)
        {
            ans[I][J] = b[i][j];
            I++;                          // ---> ++J
        }
    }
    

In the following snippet shows an alternative implementation where the matrices are modelled using a class and the merge function performs the wanted operation.

#include <algorithm>
#include <iomanip>
#include <iostream>
#include <numeric>
#include <stdexcept>
#include <vector>

template <class T>
class Matrix
{
    size_t rows_{};
    size_t cols_{};
    std::vector<T> m_;
public:
    Matrix() = default;
    Matrix(size_t r, size_t c)
        : rows_{r}, cols_{c}, m_(r * c)
    {}

    auto rows() const noexcept {
        return rows_;
    }
    auto columns() const noexcept {
        return cols_;
    }
    auto operator[] (size_t i) noexcept {
        return m_.begin() + cols_ * i;
    }
    auto operator[] (size_t i) const noexcept {
        return m_.cbegin() + cols_ * i;
    }
    auto begin() noexcept {
        return m_.begin();
    }
    auto end() noexcept {
        return m_.end();
    }
};

template <class T>
std::ostream& operator<< (std::ostream& os, Matrix<T> const& m)
{
    for (size_t i{}; i < m.rows(); ++i)
    {
        for (size_t j{}; j < m.columns(); ++j)
            os << m[i][j] << ' ';
        os << '
';
    }
    return os;
}

template<class T>
auto merge(Matrix<T> const& a, Matrix<T> const& b)
{
    if (a.rows() != b.rows())
        throw std::runtime_error{"Number of rows mismatch"};

    Matrix<T> result(a.rows(), a.columns() + b.columns());

    for (size_t i{}; i < a.rows(); ++i)
    {
        auto it = std::copy(a[i], a[i] + a.columns(), result[i]);
        std::copy(b[i], b[i] + b.columns(), it);
    }

    return result;
}


int main()
{
    int n, k;
    std::cin >> n >> k;
    int p = n - k + 1, q = n - k;

    Matrix<int> a(n, q);
    std::iota(a.begin(), a.end(), 1);
    std::cout << a << '
';

    Matrix<int> b(n, p);
    std::iota(b.begin(), b.end(), n * q + 1);
    std::cout << b << '
';

    auto c = merge(a, b);
    std::cout << c << '
';
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...