A proper way to create a matrix in c++
我想为一个图创建一个邻接矩阵。因为我读到使用
编辑:非常感谢你的快速回答。我刚刚意识到,我当然不需要任何指针。矩阵的大小将在开始时初始化,直到程序结束时才会更改。这是一个学校项目,所以如果我写"不错"的代码就好了,尽管技术性能并不太重要。使用STL很好。使用像boost之类的东西,可能是不受欢迎的。
请注意,您还可以使用boost.ublas创建和操作矩阵,也可以使用boost.graph以多种方式表示和操作图形,以及对它们使用算法等。
编辑:不管怎样,为您的目的执行向量的范围检查版本并不难:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | template <typename T> class BoundsMatrix { std::vector<T> inner_; unsigned int dimx_, dimy_; public: BoundsMatrix (unsigned int dimx, unsigned int dimy) : dimx_ (dimx), dimy_ (dimy) { inner_.resize (dimx_*dimy_); } T& operator()(unsigned int x, unsigned int y) { if (x >= dimx_ || y>= dimy_) throw std::out_of_range("matrix indices out of range"); // ouch return inner_[dimx_*y + x]; } }; |
请注意,您还需要添加运算符和/或迭代器的常量版本,以及异常的奇怪用法,但是您得到了这个想法。
默认情况下,标准向量不进行范围检查。
即,操作员[]不进行范围检查。
()处的方法与[]类似,但执行范围检查。它将引发超出范围的异常。
std::vector::at()。标准::矢量::运算符[]()
其他注释:为什么是矢量?你可以很容易地得到一个向量
1 | std::vector<std::vector<bool> > m; |
注:vector
如果在编译时知道矩阵的大小,可以使用std::bitset?
1 | std::vector<std::bitset<5> > m; |
或者,如果它是运行时定义的,则使用boost::dynamic位集
1 | std::vector<boost::dynamic_bitset> m; |
以上所有内容都允许您执行以下操作:
1 | m[6][3] = true; |
最佳方式:
创建自己的矩阵类,这样就可以控制它的每一个方面,包括范围检查。
如果你喜欢用"[X][Y]"表示法,可以这样做:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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; |
铌。如果你这样编程,那么C++和所有其他"安全"语言一样安全。
如果您想要"c"数组性能,但添加了安全性和类STL的语义(迭代器、
基本上,它是一个"c"数组的模板包装器,带有一些
我用的东西像
1 | boost::array<boost::array<float,4>,4> m; |
而不是
1 | float m[4][4]; |
一直以来,它都很好地工作(不管怎样,使用适当的typedef来保持冗长)。
更新:在这里讨论了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | #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,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 " <<"array :" << (t2-t1)/static_cast<float>(CLOCKS_PER_SEC) <<"s "; 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; } |
型
我最喜欢的图形存储方法是
除了迄今发布的所有答案之外,您还可以检查C++ FAQ Lite。问题13.10-13.12和16.16-16.19包括与滚动自己的矩阵类相关的几个主题。您将看到存储数据的几种不同方法,以及如何最好地编写下标运算符的建议。
此外,如果图足够稀疏,则可能根本不需要矩阵。您可以使用
我要做的是创建自己的类来处理矩阵(可能作为一个数组[x*y],因为我更习惯于C(并且我有自己的边界检查),但是你可以在该类中使用向量或任何其他子结构。
先让你的东西发挥功能,然后再担心它跑得有多快。如果您正确地设计了类,那么您可以拉出数组[x*y]实现,并用向量或位掩码或您想要的任何东西替换它,而不必更改其余的代码。
我不完全确定,但我认为这就是类的意义所在,它能够很好地抽象实现,并且只提供接口:—)
可能与此无关,因为这是一个古老的问题,但是您可以使用Armadillo库,它提供许多面向线性代数的数据类型和函数。
下面是您具体问题的示例:
1 2 3 4 5 6 7 8 9 10 | // In C++11 Mat<bool> matrix = { { true, true}, { false, false}, }; // In C++98 Mat<bool> matrix; matrix << true << true << endr << false << false << endr; |
请注意,
还要考虑你的图表/矩阵有多大,性能有多重要?图形是静态的,还是可以随着时间的推移而增长,例如通过添加新的边?