简体   繁体   中英

What is the best data structure for representing an upper triangular matrix in Java?

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM