We use the one-dimensional array mapping used for a lower triangular matrix
(see the class LowerTriangularMatrix).
When accessing an element (i,j)
with i >= j, the mapping formula for an
element in the lower triangle of a triangular matrix is used.
When i < j, we are accessing an element
in the upper triangle. Since the matrix is symmetric, we
access the equivalent element (j,i).
The code is given below.
The complexity of each method is readily seen to be
Theta(1).
public class LowerSymmetricMatrix
{
// data members
int rows; // matrix dimension
Object zero; // zero element
Object [] element; // element array
// constructor
public LowerSymmetricMatrix(int theRows, Object theZero)
{
// validate theRows
if (theRows < 1)
throw new IllegalArgumentException
("number of rows must be > 0");
// create and initialize the matrix
rows = theRows;
zero = theZero;
element = new Object [rows * (rows + 1) / 2];
for (int i = 0; i < rows * (rows + 1) / 2; i++)
element[i] = zero;
}
// methods
/** throws IndexOutOfBoundsException when i < 1
* or j < 1 or i > rows or j > rows */
void checkIndex(int i, int j)
{
if (i < 1 || j < 1 || i > rows || j > rows)
throw new IndexOutOfBoundsException
("i = " + i + " j = " + j +
" rows = " + rows + " cols = " + rows);
}
/** return the element this(i,j)
* throws IndexOutOfBoundsException when i or j invalid */
public Object get(int i, int j)
{
checkIndex(i, j);
if (i >= j)
return element[i * (i - 1) / 2 + j - 1];
else
// interchange roles of i and j
return element[j * (j - 1) / 2 + i - 1];
}
/** set this(i,j) = newValue
* throws IndexOutOfBoundsException when i or j invalid */
public void set(int i, int j, Object newValue)
{
checkIndex(i, j);
// store newValue
if (i >= j)
element[i * (i - 1) / 2 + j - 1] = newValue;
else
// interchange roles of i and j
element[j * (j - 1) / 2 + i - 1] = newValue;
}
}