DAY31 整數矩陣及其運算
本次代碼通過IntMatrix類封裝了二維整數矩陣的核心操作,思路如下:數據封裝→基礎操作(修改和獲取元素、獲取維度,toString返回字符串表示,getData返回內部數組引用)→矩陣運算(實現矩陣加法和乘法)→功能演示(main方法)證類的功能。
1.聲明變量
聲明了一個名為data的變量,其類型是int[][],表示這是一個二維整數數組
此處僅聲明變量,未初始化
/*** The data.*/int[][] data;
2.初始化一個整數矩陣(第一個構造方法)
這個構造方法的作用是根據指定的行數和列數,初始化矩陣的存儲空間。
接收兩個int類型參數:paraRows(行數)和paraColumns(列數)
/************************ The first constructor.* * @param paraRows* The number of rows.* @param paraColumns* The number of columns.**********************/public IntMatrix(int paraRows, int paraColumns) {data = new int[paraRows][paraColumns];}// Of the first constructor
3.創建給定矩陣的副本(第二個構造方法)
通過一個已有的二維整數數組創建一個新的IntMatrix對象(實現矩陣的復制功能)
/************************ The second constructor. Construct a copy of the given matrix.* * @param paraMatrix* The given matrix.**********************/public IntMatrix(int[][] paraMatrix) {data = new int[paraMatrix.length][paraMatrix[0].length];// Copy elements.for (int i = 0; i < data.length; i++) {for (int j = 0; j < data[0].length; j++) {data[i][j] = paraMatrix[i][j];} // Of for j} // Of for i}// Of the second constructor
4.創建給定矩陣的副本(第三個構造方法)
這行代碼實際是調用了當前類的第二個構造方法(接收int[][]參數的那個),將已有IntMatrix對象的內部數據數組作為參數傳入
這種通過this()調用其他構造方法的方式稱為構造方法重載復用,避免了代碼重復,提高了代碼的可維護性
/************************ The third constructor. Construct a copy of the given matrix.* * @param paraMatrix* The given matrix.**********************/public IntMatrix(IntMatrix paraMatrix) {this(paraMatrix.getData());}// Of the third constructor
5.getIdentityMatrix方法獲取單位矩陣
①IntMatrix resultMatrix = new IntMatrix(paraRows, paraRows);
創建一個新的IntMatrix對象,行數和列數都是paraRows(即創建一個方陣)
此時矩陣中所有元素默認值為 0(因為int類型數組的默認值是 0)
②通過循環設置對角線元素為 1
循環變量i同時表示行索引和列索引
將矩陣中(i,i)位置的元素(即主對角線上的元素)設置為 1
注釋提到 “根據訪問控制,resultMatrix.data 可以被直接訪問”,說明data成員變量的訪問權限允許在類內部直接操作
③return resultMatrix;返回創建好的單位矩陣對象
/************************ Get identity matrix. The values at the diagonal are all 1.* * @param paraRows* The given rows.**********************/public static IntMatrix getIdentityMatrix(int paraRows) {IntMatrix resultMatrix = new IntMatrix(paraRows, paraRows);for (int i = 0; i < paraRows; i++) {// According to access control, resultMatrix.data can be visited// directly.resultMatrix.data[i][i] = 1;} // Of for ireturn resultMatrix;}// Of getIdentityMatrix
6.字符串表示以及獲取內部數據
重寫toString()方法,用于返回矩陣的字符串表示形式
返回類中存儲矩陣數據的二維數組data的引用,用于外部獲取矩陣的原始數據。
/************************ Overrides the method claimed in Object, the superclass of any class.**********************/public String toString() {return Arrays.deepToString(data);}// Of toString/************************ Get my data. Warning, the reference to the data instead of a copy of the* data is returned.* * @return The data matrix.**********************/public int[][] getData() {return data;}// Of getData
7.getRows() 方法獲取矩陣行數
二維數組data的length屬性表示數組的行數(即第一維的長度)。
因此直接返回data.length即可得到矩陣的行數。
/************************ Getter.* * @return The number of rows.**********************/public int getRows() {return data.length;}// Of getRows
8.getColumns() 方法獲取矩陣列數
二維數組中,data[0]表示第一行的數組,其length屬性即為該行的元素個數,也就是矩陣的列數(假設矩陣是規則的,即每行的列數相同)。
因此返回data[0].length可得到矩陣的列數。
/************************ Getter.* * @return The number of columns.**********************/public int getColumns() {return data[0].length;}// Of getColumns
9.設置和獲取矩陣元素值
setValue() 方法設置矩陣中指定位置(行、列)的元素值。
參數說明:
paraRow:元素所在的行索引(從 0 開始)
paraColumn:元素所在的列索引(從 0 開始)
paraValue:要設置的新值(整數類型)
/************************ Set one the value of one element.* * @param paraRow* The row of the element.* @param paraColumn* The column of the element.* @param paraValue* The new value.**********************/public void setValue(int paraRow, int paraColumn, int paraValue) {data[paraRow][paraColumn] = paraValue;}// Of setValue
getValue() 方法獲取矩陣中指定位置(行、列)的元素值。
參數說明:
paraRow:元素所在的行索引(從 0 開始)
paraColumn:元素所在的列索引(從 0 開始)
返回值:指定位置的元素值(整數類型)。
實現邏輯:通過二維數組的索引訪問data[paraRow][paraColumn],并返回該位置的元素值。
/************************ Get the value of one element.* * @param paraRow* The row of the element.* @param paraColumn* The column of the element.**********************/public int getValue(int paraRow, int paraColumn) {return data[paraRow][paraColumn];}// Of getValue
10.add方法
用于將另一個矩陣與當前矩陣進行加法運算,并將結果存儲在當前矩陣中。
步驟 1:獲取傳入矩陣的數據
通過paraMatrix.getData()獲取傳入矩陣的內部二維數組tempData(注意:這里獲取的是引用,而非副本)。
// Step 1. Get the data of the given matrix.int[][] tempData = paraMatrix.getData();
步驟 2:校驗矩陣尺寸(核心前提)
矩陣加法的數學規則:只有行數和列數完全相同的兩個矩陣才能相加。
代碼通過兩個if判斷:
若當前矩陣的行數(data.length)與傳入矩陣的行數(tempData.length)不相等,拋出異常。
若當前矩陣的列數(data[0].length)與傳入矩陣的列數(tempData[0].length)不相等,拋出異常。
異常信息明確提示不匹配的維度,便于調試。
// Step 2. Size check.if (data.length != tempData.length) {throw new Exception("Cannot add matrices. Rows not match: " + data.length + " vs. "+ tempData.length + ".");} // Of ifif (data[0].length != tempData[0].length) {throw new Exception("Cannot add matrices. Rows not match: " + data[0].length + " vs. "+ tempData[0].length + ".");} // Of if
步驟 3:執行加法運算
通過雙重循環遍歷兩個矩陣的每個元素:
外層循環i遍歷行索引,內層循環j遍歷列索引。
執行data[i][j] += tempData[i][j],即當前矩陣的元素加上傳入矩陣對應位置的元素,結果存回當前矩陣。
運算規則符合矩陣加法的定義:兩個矩陣對應位置的元素相加。
// Step 3. Add to me.for (int i = 0; i < data.length; i++) {for (int j = 0; j < data[0].length; j++) {data[i][j] += tempData[i][j];} // Of for j} // Of for i
11.靜態add方法
用于對兩個已存在的矩陣進行加法運算,并返回一個新的矩陣作為結果(不修改原矩陣)。
步驟 1:克隆第一個矩陣
IntMatrix resultMatrix = new IntMatrix(paraMatrix1);:通過IntMatrix的第三個構造方法,創建paraMatrix1的副本作為結果矩陣的初始值。
這一步確保原矩陣paraMatrix1不會被修改(與實例方法add的 “修改自身” 行為不同)。
// Step 1. Clone the first matrix.IntMatrix resultMatrix = new IntMatrix(paraMatrix1);
步驟 2:執行矩陣加法
resultMatrix.add(paraMatrix2);:調用實例方法add,將paraMatrix2的元素加到resultMatrix中。
這里復用了之前實現的實例add方法的邏輯,包括尺寸校驗和元素相加,避免代碼重復。
// Step 2. Add the second one.resultMatrix.add(paraMatrix2);return resultMatrix;
12.靜態multiply方法
用于實現兩個矩陣的乘法運算,并返回一個新的矩陣作為結果
方法定義與參數
public static IntMatrix multiply(…):靜態方法,可通過類名直接調用,返回一個新的IntMatrix對象(乘法結果)。
參數paraMatrix1和paraMatrix2:分別表示要相乘的兩個矩陣(左矩陣和右矩陣)。
throws Exception:聲明可能拋出異常(當矩陣尺寸不滿足乘法條件時)。
步驟 1:校驗矩陣乘法的尺寸條件
由于矩陣乘法的數學規則:左矩陣的列數必須等于右矩陣的行數,否則無法相乘。
代碼通過if (tempData1[0].length != tempData2.length)判斷:
tempData1[0].length是左矩陣的列數
tempData2.length是右矩陣的行數
若不滿足條件,拋出異常并提示不匹配的維度。
步驟 2:為結果矩陣分配空間
矩陣乘法的結果矩陣行數 = 左矩陣的行數,列數 = 右矩陣的列數。
因此創建int[][] resultData = new int[tempData1.length][tempData2[0].length],其中:
tempData1.length是左矩陣的行數(結果矩陣的行數)
tempData2[0].length是右矩陣的列數(結果矩陣的列數)
步驟 3:執行矩陣乘法運算(核心邏輯)
通過三重循環實現矩陣乘法:
外層循環i:遍歷結果矩陣的行(對應左矩陣的行)
中層循環j:遍歷結果矩陣的列(對應右矩陣的列)
內層循環k:計算結果矩陣(i,j)位置的元素值,公式為:
resultData[i][j] = sum(左矩陣[i][k] * 右矩陣[k][j]),其中k從0到左矩陣列數-1
符合矩陣乘法的數學定義:結果矩陣的每個元素是左矩陣對應行與右矩陣對應列的元素乘積之和。
步驟 4:返回結果矩陣
通過new IntMatrix(resultData)創建結果矩陣對象并返回,原矩陣paraMatrix1和paraMatrix2的數據不會被修改。
/************************ Multiply two existing matrices.* * @param paraMatrix1* The first matrix.* @param paraMatrix2* The second matrix.* @return A new matrix.**********************/public static IntMatrix multiply(IntMatrix paraMatrix1, IntMatrix paraMatrix2)throws Exception {// Step 1. Check size.int[][] tempData1 = paraMatrix1.getData();int[][] tempData2 = paraMatrix2.getData();if (tempData1[0].length != tempData2.length) {throw new Exception("Cannot multiply matrices: " + tempData1[0].length + " vs. "+ tempData2.length + ".");} // Of if// Step 2. Allocate space.int[][] resultData = new int[tempData1.length][tempData2[0].length];// Step 3. Multiply.for (int i = 0; i < tempData1.length; i++) {for (int j = 0; j < tempData2[0].length; j++) {for (int k = 0; k < tempData1[0].length; k++) {resultData[i][j] += tempData1[i][k] * tempData2[k][j];} // Of for k} // Of for j} // Of for i// Step 4. Construct the matrix object.IntMatrix resultMatrix = new IntMatrix(resultData);return resultMatrix;}// Of multiply
13.main方法
作為程序的入口點,演示矩陣的創建、修改、乘法和加法等操作
/************************ The entrance of the program.* * @param args* Not used now.**********************/public static void main(String args[]) {IntMatrix tempMatrix1 = new IntMatrix(3, 3);tempMatrix1.setValue(0, 1, 1);tempMatrix1.setValue(1, 0, 1);tempMatrix1.setValue(1, 2, 1);tempMatrix1.setValue(2, 1, 1);System.out.println("The original matrix is: " + tempMatrix1);IntMatrix tempMatrix2 = null;try {tempMatrix2 = IntMatrix.multiply(tempMatrix1, tempMatrix1);} catch (Exception ee) {System.out.println(ee);} // Of trySystem.out.println("The square matrix is: " + tempMatrix2);IntMatrix tempMatrix3 = new IntMatrix(tempMatrix2);try {tempMatrix3.add(tempMatrix1);} catch (Exception ee) {System.out.println(ee);} // Of trySystem.out.println("The connectivity matrix is: " + tempMatrix3);}// Of main