A proper way to create a matrix in c++

后端 未结 10 2309
無奈伤痛
無奈伤痛 2020-11-27 05:33

I want to create an adjacency matrix for a graph. Since I read it is not safe to use arrays of the form matrix[x][y] because they don\'t check for range, I deci

相关标签:
10条回答
  • 2020-11-27 06:18

    Best way:

    Make your own matrix class, that way you control every last aspect of it, including range checking.

    eg. If you like the "[x][y]" notation, do this:

    class my_matrix {
      std::vector<std::vector<bool> >m;
    public:
      my_matrix(unsigned int x, unsigned int y) {
        m.resize(x, std::vector<bool>(y,false));
      }
      class matrix_row {
        std::vector<bool>& row;
      public:
        matrix_row(std::vector<bool>& r) : row(r) {
        }
        bool& operator[](unsigned int y) {
          return row.at(y);
        }
      };
      matrix_row& operator[](unsigned int x) {
        return matrix_row(m.at(x));
      }
    };
    // Example usage
    my_matrix mm(100,100);
    mm[10][10] = true;
    

    nb. If you program like this then C++ is just as safe as all those other "safe" languages.

    0 讨论(0)
  • 2020-11-27 06:24

    If you want 'C' array performance, but with added safety and STL-like semantics (iterators, begin() & end() etc), use boost::array.

    Basically it's a templated wrapper for 'C'-arrays with some NDEBUG-disable-able range checking asserts (and also some std::range_error exception-throwing accessors).

    I use stuff like

    boost::array<boost::array<float,4>,4> m;
    

    instead of

    float m[4][4];
    

    all the time and it works great (with appropriate typedefs to keep the verbosity down, anyway).


    UPDATE: Following some discussion in the comments here of the relative performance of boost::array vs boost::multi_array, I'd point out that this code, compiled with g++ -O3 -DNDEBUG on Debian/Lenny amd64 on a Q9450 with 1333MHz DDR3 RAM takes 3.3s for boost::multi_array vs 0.6s for boost::array.

    #include <iostream>
    #include <time.h>
    #include "boost/array.hpp"
    #include "boost/multi_array.hpp"
    
    using namespace boost;
    
    enum {N=1024};
    
    typedef multi_array<char,3> M;
    typedef array<array<array<char,N>,N>,N> C;
    
    // Forward declare to avoid being optimised away
    static void clear(M& m);
    static void clear(C& c);
    
    int main(int,char**)
    {
      const clock_t t0=clock();
    
      {
        M m(extents[N][N][N]);
        clear(m);
      }
    
      const clock_t t1=clock();
    
      {
        std::auto_ptr<C> c(new C);
        clear(*c);
      }
    
      const clock_t t2=clock();
    
      std::cout 
        << "multi_array: " << (t1-t0)/static_cast<float>(CLOCKS_PER_SEC) << "s\n"
        << "array      : " << (t2-t1)/static_cast<float>(CLOCKS_PER_SEC) << "s\n";
    
      return 0;
    }
    
    void clear(M& m)
    {
      for (M::index i=0;i<N;i++)
        for (M::index j=0;j<N;j++)
          for (M::index k=0;k<N;k++)
        m[i][j][k]=1;
    }
    
    
    void clear(C& c)
    {
      for (int i=0;i<N;i++)
        for (int j=0;j<N;j++)
          for (int k=0;k<N;k++)
        c[i][j][k]=1;
    }
    
    0 讨论(0)
  • 2020-11-27 06:30

    What I would do is create my own class for dealing with matrices (probably as an array[x*y] because I'm more used to C (and I'd have my own bounds checking), but you could use vectors or any other sub-structure in that class).

    Get your stuff functional first then worry about how fast it runs. If you design the class properly, you can pull out your array[x*y] implementation and replace it with vectors or bitmasks or whatever you want without changing the rest of the code.

    I'm not totally sure, but I thing that's what classes were meant for, the ability to abstract the implementation well out of sight and provide only the interface :-)

    0 讨论(0)
  • 2020-11-27 06:30

    my favourite way to store a graph is vector<set<int>>; n elements in vector (nodes 0..n-1), >=0 elements in each set (edges). Just do not forget adding a reverse copy of every bi-directional edge.

    0 讨论(0)
  • 2020-11-27 06:31

    Consider also how big is your graph/matrix, does performance matter a lot? Is the graph static, or can it grow over time, e.g. by adding new edges?

    0 讨论(0)
  • 2020-11-27 06:32

    Probably, not relevant as this is an old question, but you can use the Armadillo library, which provides many linear algebra oriented data types and functions.

    Below is an example for your specific problem:

    // In C++11
    Mat<bool> matrix = {  
        { true, true},
        { false, false},
    };
    
    // In C++98
    Mat<bool> matrix;
    matrix << true << true << endr
           << false << false << endr;
    
    0 讨论(0)
提交回复
热议问题