(a) When a triadiagonal matrix is stored by columns rows a one dimensional
array t, the mapping is t[0 : 3n −3] = [M (1,1), M (1,2), M (2,1), M (2,2),
M (2,3), M (3,2), M (3,3), M (3,4), M (4,3),
. . .
]. If |i − j | > 1, then M (i,j)
is not on the tridiagonal. For elements in the tridiagonal, we see that the
rwo 1 elements are stored in t [0] and t [1]. So, when i =1,M(i,j)isat
t[j −1]. When i > 1, there are 1−1 rows that come before the first element
of row 1. These i −1 rows contain 3(i −1) − 1 elements. Within row i,
M (i,j) is the (j − i + 2)th element. So, if i >1,M(i,j)isatt [j + 2i − 3].
When i =1,j + 2i − 3=j − 1. So, this formula may also be used for the
case i =1.
Note also that the lower diagonal is stored in positions 2, 5, 8,
. . .
of the one-dimensional array; the main diagonal occupies positions 0, 3, 6,
. . .
; and the upper diagonal ocupies positions 1, 4, 7,
. . .
.
With these bservations in mind, we arrive at the following code:
template<class T>
class TriByRows {
friend ostream& operator<<
(ostream&, const TriByRows<T>&);
friend istream& operator>>
(istream&, TriByRows<T>&);
public:
TriByRows(int size = 10)
{n = size; t = new T [3*n-2];}
~TriByRows() {delete [] t;}
TriByRows<T>& Store
(const T& x, int i, int j);
T Retrieve(int i, int j) const;
TriByRows(const TriByRows<T>& x);
// copy constructor
TriByRows<T>&
operator=(const TriByRows<T>& x);
TriByRows<T> operator+() const; // unary +
TriByRows<T>
operator+(const TriByRows<T>& x) const;
TriByRows<T> operator-() const; // unary minus
TriByRows<T>
operator-(const TriByRows<T>& x) const;
TriByRows<T>& operator+=(const T& x);
TriByRows<T> Transpose();
private:
int n; // matrix dimension
T *t; // 1D array for tridiagonal
};