C++ 上三角矩阵括号运算符
C++ Upper Triangular Matrix Bracket Operator
我的某个项目遇到了障碍。我想创建一个上三角矩阵(对角线下方的所有元素都为零),它只分配保存非零元素所需的内存。我遇到的问题是索引到这个矩阵中。我宁愿不必重新设计矩阵,但如果这是唯一的解决方案,那么我可以接受。作为旁注,Vector 是我自己的实现,而不是 stl Vector。
到目前为止,我的 class 声明如下:
template <class T>
class UMatrix : public AbstractMatrix<T>
{
private:
Vector<T>* m_data;
int m_size;
public:
//lots of member functions
};
上三角矩阵的构造函数:
template <class T>
UMatrix<T>(const int size)
{
m_size = size;
if(size < 1)
throw(RangeErr(size));
m_data = new Vector<T> [size];
for(int i = 0; i < size; i++)
{
Vector<T> init(i + 1);
m_data[i] = init;
}
}
我遇到问题的代码:
template <class T>
Vector<T>& operator[] (const int index)
{
if(m_data != NULL && index >= 0 && index < m_rows)
{
// Insert dark magic here
}
else
{
throw(RangeErr(index));
}
}
这会产生交错向量数组,每个向量的长度都比前一个大 1。
我正在尝试实现括号运算符,以便 UMatrix[a][b]
访问真正的上三角矩阵的 a 行、b 列。这意味着 UMatrix[a][b] == 0
当 a > b
.
括号运算符也是来自抽象基 class 的虚函数,并且必须 return 一个 Vector&。另外,这个实现必须使用括号运算符,而不是函数 () 运算符,以便与以前编写的代码兼容。我知道使用密集矩阵会更简单,但我只限于必要的内存使用。
我的第一次尝试涉及使用一个向量进行存储,类似于一维数组矩阵。但是,括号运算符似乎也不可能为该实现编写。
我的问题:是否可以实现这个括号运算符?
嗯,我不知道这是否是可以接受的解决方案,因为您没有提供任何关于 Vector
class 的信息。您可以创建另一个 class 让我们称之为 SparseVector<U>
,您将在其中获得这样的代码
virtual U& operator[](int i) {
if(m_data != nullptr) {
if(m_nnzb <= i && i <= m_nnze) {
return m_data[i - m_nnzb];
}
}
throw std::runtime_error("bad index: in SparseVector::operator[]");
}
这里是这个实现的思路。这是一个大小为 m_size
的向量,我们只存储 m_nnzb
到 m_nnze
范围内的非零元素。我们使用这个 class 作为矩阵 class 中的下标运算符。这是带有小示例的完整代码。
#include <iostream>
#include <exception>
#include <stdexcept>
/* vector interface */
template<typename T>
class IVector {
public:
virtual T& operator[](int i) = 0;
};
/* matrix interface */
template<typename T>
class IMatrix {
public:
virtual IVector<T>& operator[](int i) = 0;
};
/* implementation for upper triangular matrix */
template<typename T>
class UpperMatrix : public IMatrix<T> {
public:
/* implementation for sparse vector */
template<typename U>
class SparseVector : public IVector<U> {
public:
SparseVector() {
m_size = m_nnzb = m_nnze = 0;
m_data = nullptr;
}
SparseVector(int size, int b, int e) {
m_size = size;
m_nnzb = b;
m_nnze = e;
m_data = new U[e - b];
}
SparseVector(const SparseVector<U>& other) {
m_size = other.m_size;
m_nnzb = other.m_nnzb;
m_nnze = other.m_nnze;
m_data = new U[m_nnze - m_nnzb];
for(int i = 0; i < m_nnze - m_nnzb; ++i) {
m_data[i] = other.m_data[i];
}
}
virtual U& operator[](int i) {
if(m_data != nullptr) {
if(m_nnzb <= i && i <= m_nnze) {
return m_data[i - m_nnzb];
}
}
throw std::runtime_error("bad index: in SparseVector::operator[]");
}
protected:
int m_size;
int m_nnzb;
int m_nnze;
U* m_data;
};
UpperMatrix(int n) {
m_size = n;
m_data = new SparseVector<T>[n];
for(int i = 0; i < n; ++i) {
m_data[i] = SparseVector<T>(n, i, n);
}
}
virtual IVector<T>& operator[](int i) {
if(i < m_size && m_data != nullptr) {
return m_data[i];
}
throw std::runtime_error("bad index in UpperMatrix::operator[]");
}
protected:
int m_size;
SparseVector<T>* m_data;
};
int main(int argc, char** argv) {
UpperMatrix<int> m1(3);
/* correct index */
for(int i = 0; i < 3; ++i) {
for(int j = i; j < 3; ++j) {
m1[i][j] = i + j;
}
}
for(int i = 0; i < 3; ++i) {
for(int j = i; j < 3; ++j) {
std::cout << m1[i][j] << " ";
}
std::cout << std::endl;
}
/* incorrect index */
try {
for(int i = 0; i < 3; ++i) {
for(int j = 0; j < 3; ++j) {
m1[i][j] = i + j;
}
}
} catch(const std::exception& ex) {
std::cout << "error occured: " << ex.what() << std::endl;
}
}
教授更改了项目规范以允许括号运算符重载。这是解决此问题的最佳方法。
我的某个项目遇到了障碍。我想创建一个上三角矩阵(对角线下方的所有元素都为零),它只分配保存非零元素所需的内存。我遇到的问题是索引到这个矩阵中。我宁愿不必重新设计矩阵,但如果这是唯一的解决方案,那么我可以接受。作为旁注,Vector 是我自己的实现,而不是 stl Vector。
到目前为止,我的 class 声明如下:
template <class T>
class UMatrix : public AbstractMatrix<T>
{
private:
Vector<T>* m_data;
int m_size;
public:
//lots of member functions
};
上三角矩阵的构造函数:
template <class T>
UMatrix<T>(const int size)
{
m_size = size;
if(size < 1)
throw(RangeErr(size));
m_data = new Vector<T> [size];
for(int i = 0; i < size; i++)
{
Vector<T> init(i + 1);
m_data[i] = init;
}
}
我遇到问题的代码:
template <class T>
Vector<T>& operator[] (const int index)
{
if(m_data != NULL && index >= 0 && index < m_rows)
{
// Insert dark magic here
}
else
{
throw(RangeErr(index));
}
}
这会产生交错向量数组,每个向量的长度都比前一个大 1。
我正在尝试实现括号运算符,以便 UMatrix[a][b]
访问真正的上三角矩阵的 a 行、b 列。这意味着 UMatrix[a][b] == 0
当 a > b
.
括号运算符也是来自抽象基 class 的虚函数,并且必须 return 一个 Vector&。另外,这个实现必须使用括号运算符,而不是函数 () 运算符,以便与以前编写的代码兼容。我知道使用密集矩阵会更简单,但我只限于必要的内存使用。
我的第一次尝试涉及使用一个向量进行存储,类似于一维数组矩阵。但是,括号运算符似乎也不可能为该实现编写。
我的问题:是否可以实现这个括号运算符?
嗯,我不知道这是否是可以接受的解决方案,因为您没有提供任何关于 Vector
class 的信息。您可以创建另一个 class 让我们称之为 SparseVector<U>
,您将在其中获得这样的代码
virtual U& operator[](int i) {
if(m_data != nullptr) {
if(m_nnzb <= i && i <= m_nnze) {
return m_data[i - m_nnzb];
}
}
throw std::runtime_error("bad index: in SparseVector::operator[]");
}
这里是这个实现的思路。这是一个大小为 m_size
的向量,我们只存储 m_nnzb
到 m_nnze
范围内的非零元素。我们使用这个 class 作为矩阵 class 中的下标运算符。这是带有小示例的完整代码。
#include <iostream>
#include <exception>
#include <stdexcept>
/* vector interface */
template<typename T>
class IVector {
public:
virtual T& operator[](int i) = 0;
};
/* matrix interface */
template<typename T>
class IMatrix {
public:
virtual IVector<T>& operator[](int i) = 0;
};
/* implementation for upper triangular matrix */
template<typename T>
class UpperMatrix : public IMatrix<T> {
public:
/* implementation for sparse vector */
template<typename U>
class SparseVector : public IVector<U> {
public:
SparseVector() {
m_size = m_nnzb = m_nnze = 0;
m_data = nullptr;
}
SparseVector(int size, int b, int e) {
m_size = size;
m_nnzb = b;
m_nnze = e;
m_data = new U[e - b];
}
SparseVector(const SparseVector<U>& other) {
m_size = other.m_size;
m_nnzb = other.m_nnzb;
m_nnze = other.m_nnze;
m_data = new U[m_nnze - m_nnzb];
for(int i = 0; i < m_nnze - m_nnzb; ++i) {
m_data[i] = other.m_data[i];
}
}
virtual U& operator[](int i) {
if(m_data != nullptr) {
if(m_nnzb <= i && i <= m_nnze) {
return m_data[i - m_nnzb];
}
}
throw std::runtime_error("bad index: in SparseVector::operator[]");
}
protected:
int m_size;
int m_nnzb;
int m_nnze;
U* m_data;
};
UpperMatrix(int n) {
m_size = n;
m_data = new SparseVector<T>[n];
for(int i = 0; i < n; ++i) {
m_data[i] = SparseVector<T>(n, i, n);
}
}
virtual IVector<T>& operator[](int i) {
if(i < m_size && m_data != nullptr) {
return m_data[i];
}
throw std::runtime_error("bad index in UpperMatrix::operator[]");
}
protected:
int m_size;
SparseVector<T>* m_data;
};
int main(int argc, char** argv) {
UpperMatrix<int> m1(3);
/* correct index */
for(int i = 0; i < 3; ++i) {
for(int j = i; j < 3; ++j) {
m1[i][j] = i + j;
}
}
for(int i = 0; i < 3; ++i) {
for(int j = i; j < 3; ++j) {
std::cout << m1[i][j] << " ";
}
std::cout << std::endl;
}
/* incorrect index */
try {
for(int i = 0; i < 3; ++i) {
for(int j = 0; j < 3; ++j) {
m1[i][j] = i + j;
}
}
} catch(const std::exception& ex) {
std::cout << "error occured: " << ex.what() << std::endl;
}
}
教授更改了项目规范以允许括号运算符重载。这是解决此问题的最佳方法。