稀疏矩阵的转置
设带转置矩阵 A 的列为 col,共有 num 个元素,
使用了两种方法进行转置,一种时间复杂度是 O(col* num),一种时间复杂度是O(max(col, num))
//矩阵中的元素
class Item {
int row;
int col;
int item;
public Item(int row, int col, int item) {
this.row = row;
this.col = col;
this.item = item;
}
}
//系数矩阵的定义
class SparseMatrix {
Item[] elements;
int num; //元素个数
public SparseMatrix(int num) {
this.num = num;
elements = new Item[num];
}
}
public class MatrixTran {
public static void main(String[] args) {
SparseMatrix matrixA = new SparseMatrix(8);
initMatrix(matrixA.elements);
for (Item item : matrixA.elements) {
System.out.printf("[%d, %d, %d]\n", item.row, item.col, item.item);
}
System.out.println("------------------------------------------------------");
//method1(matrixA);
method2(matrixA);
}
/**
* 该方法的时间复杂度为 O(col * nums),思路就是简化后的遍历整个二维数组,现在就是不用遍历所有的元素,只需要在总元素范围内遍历就可
* @param matrixA
*/
private static void method1(SparseMatrix matrixA) {
//初始化转置后的矩阵
SparseMatrix matrixB = new SparseMatrix(8);
Item[] elemsB = matrixB.elements;
for(int i = 0; i < 8; i++) {
elemsB[i] = new Item(0, 0, 0);
}
//使用时间复杂度为 O(col * number) 的算法
int currentPos = 0;
Item[] elemsA = matrixA.elements;
for(int i = 0; i < 7; i++) {
for(int j = 0; j < matrixA.num; j++) {
if(i == elemsA[j].col) {
elemsB[currentPos].row = elemsA[j].col;
elemsB[currentPos].col = elemsA[j].row;
elemsB[currentPos].item = elemsA[j].item;
currentPos++;
}
}
}
for (Item item : elemsB) {
System.out.printf("[%d, %d, %d]\n", item.row, item.col, item.item);
}
}
/**
* 方法二:时间复杂度为 O(max(A.cols, A.nums))
* 思路:
* 1、矩阵 A 经过转置变成 B 之后,列变成了行,我们先用一个数组 rowSize 来存储 B 的每行中有几个元素
* 2、再用一个数组 rowStart 来存储 B 的每行第一个元素的起始位置,就是 rowSize[i - 1] + rowStart[i - 1]
* 3、遍历 A 中的元素,每遍历到一个元素,我们就通过 rowStart[A.col] 来确定它的起始位置,
* 在 B 中添加元素之后,把对应的该元素所在行的起始位置加一,以便下一个该行的元素可以知道自己的起始位置
* @param matrixA
*/
private static void method2(SparseMatrix matrixA) {
//获得矩阵 A 中元素
Item[] elemsA = matrixA.elements;
//创建矩阵 B 并初始化
SparseMatrix matrixB = new SparseMatrix(8);
Item[] elemsB = matrixB.elements;
for(int i = 0; i < 8; i++) {
elemsB[i] = new Item(0, 0, 0);
}
//定义每行的元素总个数
int[] rowSize = new int[8];
//定义每行元素的起始位置
int[] rowStart = new int[8];
//初始化
for(int i = 0; i < 8; i++) {
rowSize[i] = 0;
rowStart[i] = 0;
}
//设置每行元素有多少个
for (Item item : elemsA) {
rowSize[item.col]++;
}
//设置每行的第一个元素的起始位置
for(int i = 0; i < matrixA.num; i ++) {
if(i > 0) {
rowStart[i] = rowStart[i - 1] + rowSize[i - 1];
}
}
//往目标数组里面放元素
for (Item item : elemsA) {
int rowB = item.col;
int pos = rowStart[rowB]; //pos 就是该元素在矩阵 A 中应该存储的位置
elemsB[pos].row = item.col;
elemsB[pos].col = item.row;
elemsB[pos].item = item.item;
rowStart[rowB]++;
}
//输出
for (Item item : elemsB) {
System.out.printf("[%d, %d, %d]\n", item.row, item.col, item.item);
}
}
//初始化矩阵A
private static void initMatrix(Item[] matrix) {
matrix[0] = new Item(0, 2, 22);
matrix[1] = new Item(0, 6, 15);
matrix[2] = new Item(1, 1, 11);
matrix[3] = new Item(1, 5, 17);
matrix[4] = new Item(2, 3, -6);
matrix[5] = new Item(3, 5, 39);
matrix[6] = new Item(4, 0, 91);
matrix[7] = new Item(5, 2, 28);
}
}