线性代数

掌握矩阵运算、线性系统求解和高级线性代数技术

概述

线性代数是现代算法的数学基础,在图形学、机器学习、网络分析等领域有广泛应用。本章节深入探讨矩阵运算、高斯消元法、特征值计算等核心技术,为解决复杂的线性系统问题提供强大工具。

核心内容

1. 基础矩阵运算

矩阵运算是线性代数的基础,包括加法、乘法、转置等基本操作。

// 基础矩阵运算实现
#include <iostream>
#include <vector>
#include <iomanip>
using namespace std;

class Matrix {
private:
    vector<vector<double>> data;
    int rows, cols;

public:
    Matrix(int r, int c) : rows(r), cols(c) {
        data.resize(r, vector<double>(c, 0));
    }
    
    Matrix(vector<vector<double>>& mat) {
        data = mat;
        rows = mat.size();
        cols = mat[0].size();
    }
    
    // 矩阵加法
    Matrix operator+(const Matrix& other) const {
        if (rows != other.rows || cols != other.cols) {
            throw invalid_argument("矩阵维度不匹配");
        }
        
        Matrix result(rows, cols);
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                result.data[i][j] = data[i][j] + other.data[i][j];
            }
        }
        return result;
    }
    
    // 矩阵乘法
    Matrix operator*(const Matrix& other) const {
        if (cols != other.rows) {
            throw invalid_argument("矩阵维度不匹配");
        }
        
        Matrix result(rows, other.cols);
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < other.cols; j++) {
                for (int k = 0; k < cols; k++) {
                    result.data[i][j] += data[i][k] * other.data[k][j];
                }
            }
        }
        return result;
    }
    
    // 矩阵转置
    Matrix transpose() const {
        Matrix result(cols, rows);
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                result.data[j][i] = data[i][j];
            }
        }
        return result;
    }
    
    // 矩阵快速幂(用于递推关系)
    Matrix power(long long n) const {
        if (rows != cols) {
            throw invalid_argument("非方阵无法求幂");
        }
        
        Matrix result = identity(rows);
        Matrix base = *this;
        
        while (n > 0) {
            if (n % 2 == 1) {
                result = result * base;
            }
            base = base * base;
            n /= 2;
        }
        return result;
    }
    
    // 创建单位矩阵
    static Matrix identity(int n) {
        Matrix result(n, n);
        for (int i = 0; i < n; i++) {
            result.data[i][i] = 1;
        }
        return result;
    }
    
    // 打印矩阵
    void print() const {
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                cout << setw(8) << fixed << setprecision(2) << data[i][j] << " ";
            }
            cout << endl;
        }
    }
    
    double& operator()(int i, int j) { return data[i][j]; }
    const double& operator()(int i, int j) const { return data[i][j]; }
    int getRows() const { return rows; }
    int getCols() const { return cols; }
};

// 应用:斐波那契数列的矩阵快速计算
long long fibonacciMatrix(int n) {
    if (n <= 1) return n;
    
    // 转移矩阵 [[1,1],[1,0]]
    vector<vector<double>> trans = {{1, 1}, {1, 0}};
    Matrix transition(trans);
    
    Matrix result = transition.power(n - 1);
    return (long long)(result(0, 0) + 0.5); // 四舍五入
}

int main() {
    // 测试基础运算
    vector<vector<double>> a = {{1, 2}, {3, 4}};
    vector<vector<double>> b = {{5, 6}, {7, 8}};
    
    Matrix A(a), B(b);
    
    cout << "矩阵A:" << endl;
    A.print();
    
    cout << "\n矩阵B:" << endl;
    B.print();
    
    cout << "\nA + B:" << endl;
    (A + B).print();
    
    cout << "\nA * B:" << endl;
    (A * B).print();
    
    cout << "\nA的转置:" << endl;
    A.transpose().print();
    
    // 测试矩阵快速幂
    cout << "\n斐波那契数列前10项:" << endl;
    for (int i = 0; i <= 10; i++) {
        cout << "F(" << i << ") = " << fibonacciMatrix(i) << endl;
    }
    
    return 0;
}

2. 高斯消元法

高斯消元法是求解线性方程组的经典算法,也是计算矩阵逆、行列式的基础。

// 高斯消元法实现
#include <iostream>
#include <vector>
#include <cmath>
#include <iomanip>
using namespace std;

const double EPS = 1e-9;

class LinearSystem {
private:
    vector<vector<double>> augmented;
    int n, m;

public:
    LinearSystem(vector<vector<double>>& A, vector<double>& b) {
        n = A.size();
        m = A[0].size();
        augmented.resize(n, vector<double>(m + 1));
        
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                augmented[i][j] = A[i][j];
            }
            augmented[i][m] = b[i];
        }
    }
    
    // 高斯消元求解线性方程组
    vector<double> solve() {
        int rank = 0;
        vector<int> pivot_col(n, -1);
        
        for (int col = 0; col < m && rank < n; col++) {
            // 寻找主元
            int pivot_row = -1;
            for (int row = rank; row < n; row++) {
                if (abs(augmented[row][col]) > EPS) {
                    if (pivot_row == -1 || abs(augmented[row][col]) > abs(augmented[pivot_row][col])) {
                        pivot_row = row;
                    }
                }
            }
            
            if (pivot_row == -1) continue; // 当前列全为0
            
            // 交换行
            if (pivot_row != rank) {
                swap(augmented[pivot_row], augmented[rank]);
            }
            
            pivot_col[rank] = col;
            
            // 消元
            for (int row = 0; row < n; row++) {
                if (row != rank && abs(augmented[row][col]) > EPS) {
                    double factor = augmented[row][col] / augmented[rank][col];
                    for (int j = col; j <= m; j++) {
                        augmented[row][j] -= factor * augmented[rank][j];
                    }
                }
            }
            rank++;
        }
        
        // 检查解的存在性
        for (int i = rank; i < n; i++) {
            if (abs(augmented[i][m]) > EPS) {
                throw runtime_error("方程组无解");
            }
        }
        
        vector<double> solution(m, 0);
        for (int i = 0; i < rank; i++) {
            if (pivot_col[i] != -1) {
                solution[pivot_col[i]] = augmented[i][m] / augmented[i][pivot_col[i]];
            }
        }
        
        return solution;
    }
    
    // 计算矩阵的秩
    int getRank() {
        int rank = 0;
        for (int col = 0; col < m && rank < n; col++) {
            int pivot_row = -1;
            for (int row = rank; row < n; row++) {
                if (abs(augmented[row][col]) > EPS) {
                    pivot_row = row;
                    break;
                }
            }
            
            if (pivot_row == -1) continue;
            
            if (pivot_row != rank) {
                swap(augmented[pivot_row], augmented[rank]);
            }
            
            for (int row = rank + 1; row < n; row++) {
                if (abs(augmented[row][col]) > EPS) {
                    double factor = augmented[row][col] / augmented[rank][col];
                    for (int j = col; j <= m; j++) {
                        augmented[row][j] -= factor * augmented[rank][j];
                    }
                }
            }
            rank++;
        }
        return rank;
    }
};

// 计算行列式
double determinant(vector<vector<double>> matrix) {
    int n = matrix.size();
    double det = 1;
    
    for (int i = 0; i < n; i++) {
        // 寻找主元
        int pivot = i;
        for (int j = i + 1; j < n; j++) {
            if (abs(matrix[j][i]) > abs(matrix[pivot][i])) {
                pivot = j;
            }
        }
        
        if (abs(matrix[pivot][i]) < EPS) return 0; // 矩阵奇异
        
        if (pivot != i) {
            swap(matrix[i], matrix[pivot]);
            det = -det; // 交换行改变符号
        }
        
        det *= matrix[i][i];
        
        // 消元
        for (int j = i + 1; j < n; j++) {
            if (abs(matrix[j][i]) > EPS) {
                double factor = matrix[j][i] / matrix[i][i];
                for (int k = i; k < n; k++) {
                    matrix[j][k] -= factor * matrix[i][k];
                }
            }
        }
    }
    
    return det;
}

// 矩阵求逆
vector<vector<double>> inverse(vector<vector<double>> A) {
    int n = A.size();
    vector<vector<double>> inv(n, vector<double>(n, 0));
    
    // 创建增广矩阵 [A|I]
    for (int i = 0; i < n; i++) {
        inv[i][i] = 1;
    }
    
    // 高斯-约旦消元
    for (int i = 0; i < n; i++) {
        // 寻找主元
        int pivot = i;
        for (int j = i + 1; j < n; j++) {
            if (abs(A[j][i]) > abs(A[pivot][i])) {
                pivot = j;
            }
        }
        
        if (abs(A[pivot][i]) < EPS) {
            throw runtime_error("矩阵不可逆");
        }
        
        if (pivot != i) {
            swap(A[i], A[pivot]);
            swap(inv[i], inv[pivot]);
        }
        
        // 归一化主元行
        double pivot_val = A[i][i];
        for (int j = 0; j < n; j++) {
            A[i][j] /= pivot_val;
            inv[i][j] /= pivot_val;
        }
        
        // 消元
        for (int j = 0; j < n; j++) {
            if (j != i && abs(A[j][i]) > EPS) {
                double factor = A[j][i];
                for (int k = 0; k < n; k++) {
                    A[j][k] -= factor * A[i][k];
                    inv[j][k] -= factor * inv[i][k];
                }
            }
        }
    }
    
    return inv;
}

int main() {
    // 测试线性方程组求解
    vector<vector<double>> A = {
        {2, 1, -1},
        {-3, -1, 2},
        {-2, 1, 2}
    };
    vector<double> b = {8, -11, -3};
    
    LinearSystem system(A, b);
    
    try {
        vector<double> solution = system.solve();
        cout << "方程组解:" << endl;
        for (int i = 0; i < solution.size(); i++) {
            cout << "x" << i + 1 << " = " << fixed << setprecision(4) << solution[i] << endl;
        }
    } catch (const exception& e) {
        cout << "错误: " << e.what() << endl;
    }
    
    // 测试行列式计算
    vector<vector<double>> B = {{1, 2, 3}, {4, 5, 6}, {7, 8, 10}};
    cout << "\n行列式: " << determinant(B) << endl;
    
    // 测试矩阵求逆
    try {
        vector<vector<double>> C = {{2, 1}, {1, 1}};
        vector<vector<double>> inv_C = inverse(C);
        cout << "\n逆矩阵:" << endl;
        for (auto& row : inv_C) {
            for (double val : row) {
                cout << setw(8) << fixed << setprecision(4) << val << " ";
            }
            cout << endl;
        }
    } catch (const exception& e) {
        cout << "错误: " << e.what() << endl;
    }
    
    return 0;
}

3. 高级应用

特征值与特征向量

特征值分解在图论、主成分分析、马尔可夫链等问题中有重要应用。

// 幂迭代法求最大特征值
#include <iostream>
#include <vector>
#include <cmath>
#include <random>
using namespace std;

// 向量运算
double dotProduct(const vector<double>& a, const vector<double>& b) {
    double sum = 0;
    for (int i = 0; i < a.size(); i++) {
        sum += a[i] * b[i];
    }
    return sum;
}

double vectorNorm(const vector<double>& v) {
    return sqrt(dotProduct(v, v));
}

vector<double> normalize(const vector<double>& v) {
    double norm = vectorNorm(v);
    vector<double> result(v.size());
    for (int i = 0; i < v.size(); i++) {
        result[i] = v[i] / norm;
    }
    return result;
}

vector<double> matrixVectorMultiply(const vector<vector<double>>& A, const vector<double>& v) {
    int n = A.size();
    vector<double> result(n, 0);
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            result[i] += A[i][j] * v[j];
        }
    }
    return result;
}

// 幂迭代法
pair<double, vector<double>> powerIteration(const vector<vector<double>>& A, int maxIter = 1000, double tol = 1e-9) {
    int n = A.size();
    
    // 初始化随机向量
    random_device rd;
    mt19937 gen(rd());
    uniform_real_distribution<> dis(-1.0, 1.0);
    
    vector<double> v(n);
    for (int i = 0; i < n; i++) {
        v[i] = dis(gen);
    }
    v = normalize(v);
    
    double eigenvalue = 0;
    for (int iter = 0; iter < maxIter; iter++) {
        vector<double> Av = matrixVectorMultiply(A, v);
        double newEigenvalue = dotProduct(v, Av);
        
        if (abs(newEigenvalue - eigenvalue) < tol) {
            return {newEigenvalue, normalize(Av)};
        }
        
        eigenvalue = newEigenvalue;
        v = normalize(Av);
    }
    
    return {eigenvalue, v};
}

// 图的邻接矩阵分析
class GraphAnalysis {
private:
    vector<vector<double>> adj;
    int n;

public:
    GraphAnalysis(vector<vector<int>>& edges, int nodes) : n(nodes) {
        adj.resize(n, vector<double>(n, 0));
        
        // 构建邻接矩阵
        for (auto& edge : edges) {
            adj[edge[0]][edge[1]] = 1;
            adj[edge[1]][edge[0]] = 1; // 无向图
        }
    }
    
    // 计算图的谱半径(最大特征值)
    double spectralRadius() {
        auto result = powerIteration(adj);
        return result.first;
    }
    
    // PageRank算法(修改的幂迭代)
    vector<double> pageRank(double damping = 0.85, int maxIter = 1000, double tol = 1e-9) {
        // 构建转移矩阵
        vector<vector<double>> P(n, vector<double>(n, 0));
        vector<int> outDegree(n, 0);
        
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if (adj[i][j] > 0) outDegree[i]++;
            }
        }
        
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if (outDegree[i] > 0) {
                    P[j][i] = adj[i][j] / outDegree[i];
                } else {
                    P[j][i] = 1.0 / n; // 处理悬挂节点
                }
            }
        }
        
        // PageRank迭代
        vector<double> rank(n, 1.0 / n);
        
        for (int iter = 0; iter < maxIter; iter++) {
            vector<double> newRank(n, (1 - damping) / n);
            
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < n; j++) {
                    newRank[i] += damping * P[i][j] * rank[j];
                }
            }
            
            // 检查收敛
            double diff = 0;
            for (int i = 0; i < n; i++) {
                diff += abs(newRank[i] - rank[i]);
            }
            
            if (diff < tol) break;
            rank = newRank;
        }
        
        return rank;
    }
};

int main() {
    // 测试特征值计算
    vector<vector<double>> matrix = {
        {4, 1, 0},
        {1, 3, 1},
        {0, 1, 2}
    };
    
    auto result = powerIteration(matrix);
    cout << "最大特征值: " << result.first << endl;
    cout << "对应特征向量:" << endl;
    for (double val : result.second) {
        cout << val << " ";
    }
    cout << endl;
    
    // 测试图分析
    vector<vector<int>> edges = {{0, 1}, {1, 2}, {2, 0}, {1, 3}, {3, 4}, {4, 1}};
    GraphAnalysis graph(edges, 5);
    
    cout << "\n图的谱半径: " << graph.spectralRadius() << endl;
    
    vector<double> pagerank = graph.pageRank();
    cout << "\nPageRank值:" << endl;
    for (int i = 0; i < pagerank.size(); i++) {
        cout << "节点 " << i << ": " << pagerank[i] << endl;
    }
    
    return 0;
}

解题技巧

⚡ 数值稳定性

使用部分主元选择避免数值不稳定,设置合适的精度阈值,注意浮点数比较的陷阱。

🎯 算法选择

根据问题特点选择算法:稠密矩阵用高斯消元,稀疏矩阵考虑迭代方法,大规模问题使用近似算法。

💡 优化技巧

利用矩阵的特殊性质(对称、三对角等)优化算法,使用块矩阵分解处理大规模问题。

🔍 应用识别

识别线性代数在不同领域的应用:图论中的邻接矩阵、机器学习中的主成分分析、网络分析中的PageRank。