Suppose an upper triangular matrix of integers is given. What's the best way of storing this in Java? The naive 2d int array is obviously not efficient. The solution I came up with was moved to the answers section.
If you want to save memory, your solution looks great - it's called a packed storage matrix . Column by column, top down, your array would look like this: 1 2 6 3 7 8 4 1 9 5
I would suggest a simpler calculation of your indices, based on the sum formula (n² + n) / 2
( row and column is zero based).
list_index = (column^2 + column) / 2 + row;
An implementation could look like the following:
public class TriangularMatrix {
private final int[] list;
public TriangularMatrix(int size) {
list = new int[sumFormula(size)];
}
public int set(int row, int column, int value) {
validateArguments(row, column);
int listIndex = getListIndex(row, column);
int oldValue = list[listIndex];
list[listIndex] = value;
return oldValue;
}
public int get(int row, int column) {
validateArguments(row, column);
return list[getListIndex(row, column)];
}
private void validateArguments(int row, int column) {
if (row > column) {
throw new IllegalArgumentException("Row (" + row + " given) has to be smaller or equal than column (" + column + " given)!");
}
}
private int getListIndex(int row, int column) {
return sumFormula(column) + row;
}
private int sumFormula(int i) {
return (i*i + i) / 2;
}
}
There is another question on SO discussing the (negative) performance impact, although it's about Fortran.
What about Guava's Table
? It is implemented using HashMaps or TreeMaps (as well as 2D array if required), but it offers much nicer API than defining a Map<Integer, Map<Integer, V>>
.
If the matrix is always diagonal, I would use:
List<List<Integer>> matrix = ...
If it is an sparse matrix, I would use maps:
Map<Map<Integer>> = ...
In this second case, you may need to wrap the map in a class with get and set operations in order to manage access to new rows and columns.
All this, however depends on your needs, your memory limites and matrix size.
I think I found the solution. Here is my solution: Assume you have a 4X4 upper triangular matrix M.
1 2 3 4
0 6 7 1
0 0 8 9
0 0 0 5
If you can map every element of M in a 1d array, that's the best solution. All you need to know is to know which [row,col] of matrix corresponds to which element of your 1d array. Here is how you do the magic:
start_index=((col_index-1)+1)+((col_index-2)+1)+...+1
end_index=start_index + col_index
For example: if I want to find where are the elements on the 3rd column of the matrix, in the array:
start_index=((3-1)+1)+((3-2)+1)+((3-3)+1)=6
end_index=6+3=9
So, all I need to do is to start at index 6 of my array, and read all the elements till index 9 (including 9th element). Following this procedure, then you can store and retrieve all the cells of the nXn matrix in (n + n^2)/2 space.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.