目錄
矩陣的傳統表示:二維數組
🔍 真正有用的數據是哪些?
從二維數組轉為一維數組
用 C++ 類實現對角矩陣
1. 對角矩陣真正需要存什么?
2. 對角矩陣允許哪些行為?
3. 為什么要動態分配數組?
接下來推導每個函數如何實現
什么是對角矩陣?
在一個正方形矩陣中:只有主對角線(左上到右下)上的元素可能非零,其余全為零。
舉個例子:3x3 對角矩陣
A = | 1 0 0 || 0 2 0 || 0 0 3 |
只有 A[0][0]
, A[1][1]
, A[2][2]
非零,其余全是 0
?? 實質是一個表格,每個位置用兩個索引 i
和 j
訪問:A[i][j]
矩陣的傳統表示:二維數組
在 C++ 里我們通常用二維數組來表示矩陣:
int A[3][3]; // 表示一個 3×3 的矩陣
例如:
A[0][0] A[0][1] A[0][2]
A[1][0] A[1][1] A[1][2]
A[2][0] A[2][1] A[2][2]
?總共有 n^2?個元素,每個都有自己的位置。
?問題來了:如果矩陣是稀疏的或有結構的,這個方式會浪費空間。
對角矩陣是一個非常特殊的矩陣:
-
只有對角線(
i == j
)上的元素可能非 0 -
其他所有元素(
i ≠ j
)都為 0
🔍 真正有用的數據是哪些?
觀察這個對角矩陣:
我們可以問自己兩個問題:
?哪些元素值我們真正關心?
?哪些元素值是注定為 0、不需要存?
答案很明顯:
條件 | 是否有用 | 存儲與否 |
---|---|---|
i == j | ?是對角線 → 非零元素 → 必須存 | ? 存 |
i ≠ j | ?一定是 0,無需存儲 | ? 不存 |
所以,對角矩陣只需要存儲 n 個元素!
我們就可以只用一個 一維數組 存這些元素:
//只存儲對角線上的元素
int D[n]; // D[0] 存 A[0][0], D[1] 存 A[1][1], ..., D[n-1] 存 A[n-1][n-1]
從二維數組轉為一維數組
我們的問題是:
給定任意 (i, j)
,如何通過簡單規則判斷:
-
要不要存儲?
-
如果要 → 存在 D[] 中哪一項?
觀察這個矩陣:
A[0][0] A[0][1] A[0][2]
A[1][0] A[1][1] A[1][2]
A[2][0] A[2][1] A[2][2]
我們對每一個 (i, j)
做判斷:
-
如果
i != j
:一定是 0,不存 -
如果
i == j
:對角線 → 存在D[i]
中
訪問時:如何從 (i,j)
得到實際值?
-
如果
i == j
:返回 D[i] -
如果
i != j
:說明是非對角元素 ? 返回 0
int get(int D[], int i, int j) {if (i == j)return D[i];elsereturn 0;
}
插入時:如何通過 (i, j) 更新值?
-
如果
i == j
:表示是在對角線上,我們需要更新存儲數組D[i] = value
-
如果
i != j
:不允許存儲,非對角線值必須為 0 ? 忽略或報錯
void set(int D[], int i, int j, int value) {if (i == j)D[i] = value;else if (value != 0)cout << "Error: Only diagonal elements can be non-zero.\n";
}
用 C++ 類實現對角矩陣
第一性思考:我們要封裝什么?
我們希望把對角矩陣的數據 + 行為都封裝起來,變成一個可用的抽象對象。
所以我們問自己三個關鍵問題:
1. 對角矩陣真正需要存什么?
-
只需要存對角線上的元素:
D[0]~D[n-1]
-
也就是一個一維數組 + 大小信息
→ 數據成員:
int* D; // 存儲數據(動態分配)
int n; // 矩陣大小 n × n
2. 對角矩陣允許哪些行為?
行為也就是 成員函數(methods),我們一一推導:
功能 | 描述 |
---|---|
set(i, j, x) | 如果 i==j ,設置 D[i]=x,否則忽略或報錯 |
get(i, j) | 如果 i==j 返回 D[i],否則返回 0 |
display() | 打印整個 n×n 矩陣 |
構造函數 | 初始化數組大小和空間 |
析構函數 | 釋放分配的堆內存 |
3. 為什么要動態分配數組?
-
因為用戶可以創建任意大小的矩陣
n×n
-
所以不能用靜態數組,必須用
new int[n]
動態分配
?抽象轉為結構:類的原型
class DiagonalMatrix {
private:int* D; // 一維數組int n; // 階數public:DiagonalMatrix(int size); // 構造函數~DiagonalMatrix(); // 析構函數void set(int i, int j, int value); // 設置元素int get(int i, int j); // 獲取元素void display(); // 打印矩陣
};
接下來推導每個函數如何實現
1. 構造函數
目標:接受一個 size,創建一個對角矩陣
DiagonalMatrix::DiagonalMatrix(int size) {n = size;D = new int[n]; // 創建對角線存儲for (int i = 0; i < n; i++) D[i] = 0; // 初始化為 0
}
2. 析構函數
釋放堆空間,防止內存泄露:
DiagonalMatrix::~DiagonalMatrix() {delete[] D;
}
3. set(i, j, value)
void DiagonalMatrix::set(int i, int j, int value) {if (i >= 0 && i < n && j >= 0 && j < n) {if (i == j)D[i] = value;else if (value != 0)cout << "Error: only diagonal elements can be non-zero.\n";} else {cout << "Error: index out of bounds.\n";}
}
4. get(i, j)
int DiagonalMatrix::get(int i, int j) {if (i >= 0 && i < n && j >= 0 && j < n) {if (i == j)return D[i];elsereturn 0;} else {cout << "Error: index out of bounds.\n";return -1;}
}
5. display()
void DiagonalMatrix::display() {for (int i = 0; i < n; i++) {for (int j = 0; j < n; j++) {if (i == j)cout << D[i] << " ";elsecout << "0 ";}cout << endl;}
}
最終完整使用示例(main)
int main() {DiagonalMatrix dm(4); // 創建一個 4×4 的對角矩陣dm.set(0, 0, 5);dm.set(1, 1, 9);dm.set(2, 2, 3);dm.set(3, 3, 7);dm.set(0, 1, 99); // 應報錯:非對角元素dm.display();cout << "dm[2][2] = " << dm.get(2, 2) << endl;return 0;
}
總結(類設計第一性路徑圖)
對角矩陣↓
只需保存 D[0..n-1]↓
封裝成類 DiagonalMatrix↓
數據成員:- int* D // 動態存儲對角線- int n // 階數↓
方法設計:- 構造函數:new 分配- 析構函數:delete 釋放- set(i,j,x):僅 i==j 時設置- get(i,j):i==j 返回 D[i],否則 0- display():顯示整個矩陣