Какова наилучшая структура данных для представления верхней треугольной матрицы в Java?

предположим, что задана верхняя треугольная матрица целых чисел. Каков наилучший способ хранения этого на Java? Наивный 2D int массив, очевидно, не эффективен. Решение, которое я придумал, было перенесено в раздел ответов.

4 ответов


Как насчет гуавы Table? Он реализован с использованием HashMaps или TreeMaps (а также 2D-массива, если требуется), но он предлагает гораздо более приятный API, чем определение Map<Integer, Map<Integer, V>>.


если вы хотите сохранить память, ваше решение выглядит здорово - это называется упакованная матрица хранения. По столбцам, сверху-вниз, Ваш массив будет выглядеть так: 1 2 6 3 7 8 4 1 9 5

Я бы предложил более простой расчет индексов на основе формулы сумме (n² + n) / 2 (строка и колонки начинается с нуля).

list_index = (column^2 + column) / 2 + row;

реализация может выглядеть следующим образом:

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;
    }
}

здесь еще один вопрос так обсуждение (отрицательного) влияния на производительность, хотя речь идет о Fortran.


если матрица всегда диагональна, я бы использовал:

List<List<Integer>> matrix = ...

Если это разреженная матрица, я бы использовал карты:

Map<Map<Integer>> = ...

во втором случае может потребоваться обернуть карту в класс с операциями get и set для управления доступом к новым строкам и столбцам.

все это, однако, зависит от ваших потребностей, ограничений памяти и размера матрицы.


Я думаю, что нашел решение. Вот мое решение: Предположим, у вас есть верхняя треугольная матрица 4X4 M.

1 2 3 4
0 6 7 1
0 0 8 9
0 0 0 5

Если вы можете отобразить каждый элемент M в массиве 1d, это лучшее решение. Все, что вам нужно знать-это знать, что [строка,колонка] матрицы соответствует элементу массива 1д. Вот как вы делаете магию:

start_index=((col_index-1)+1)+((col_index-2)+1)+...+1
end_index=start_index + col_index

например: если я хочу найти, где находятся элементы в 3-м столбце матрицы, в массив:

start_index=((3-1)+1)+((3-2)+1)+((3-3)+1)=6
end_index=6+3=9

Итак, все, что мне нужно сделать, это начать с индекса 6 моего массива и прочитать все элементы до индекса 9 (включая 9-й элемент). Следуя этой процедуре, вы можете сохранить и получить все ячейки матрицы nXn в (n + n^2)/2 пространстве.