引言
数据结构与算法中,矩阵是一个重要的概念,它既是数据结构的一种,也是算法中经常需要处理的对象。以下是对矩阵的详细介绍:
一、矩阵的定义
矩阵(Matrix)是一个按照长方阵列排列的复数或实数集合,它是一个二维的数据结构,由行和列组成,通常用来表示二维的数据集合。在数学中,矩阵最早来自于方程组的系数及常数所构成的方阵,这一概念由19世纪英国数学家凯利首先提出。在数据结构中,矩阵主要讨论如何在节省存储空间的前提下,正确高效地运算矩阵。
二、矩阵的特征
- 二维数组:矩阵也可以看作是一个二维数组,即"数组的数组"。
- 元素类型:矩阵的元素可以是数字、字符、布尔值等类型。
- 非线性结构:虽然矩阵表面上看似不符合线性表的特征(如首结点不唯一、尾结点不唯一、中间结点有两个直接前驱和两个直接后驱),但实质上,我们可以把每行(或每列)数据看成一个整体,作为一个数据元素,那么矩阵就符合线性表的特征,只是每个数据元素的类型又是一个线性表。
三、矩阵的存储方式
- 按行优先顺序存储:即将数组元素按行排序,第i+1行的第一个元素紧接在第i行的最后一个元素的后面。
- 按列优先顺序存储:即将数组元素按列排序,第j+1列的第一个元素紧接在第j列的最后一个元素的后面。
四、矩阵的运算
矩阵的运算包括加法、减法、乘法、转置等。
- 加法与减法:矩阵的加法和减法要求两个矩阵的维数相同,即行数和列数都必须相等,然后对应位置的元素进行加或减运算。
- 乘法:矩阵的乘法不是简单的对应位置元素相乘,而是按照矩阵乘法规则进行计算,即第一个矩阵的行向量与第二个矩阵的列向量进行点积运算。
- 转置:矩阵的转置是将矩阵的行和列互换,即原矩阵的第i行第j列元素在转置矩阵中变为第j行第i列元素。
五、矩阵的应用
矩阵在计算机科学中有着广泛的应用,比如在机器学习和人工智能领域中,矩阵被用来表示数据集合和模型参数,进行数据处理和计算。在图形学中,矩阵被用来表示图像的像素值和进行图像处理操作。在网络编程中,矩阵也被用来表示网络拓扑结构和进行数据传输。此外,在物理学、工程学、经济学等多个领域,矩阵也有着重要的应用。
六、特殊矩阵
- 对称矩阵:在一个n阶方阵中,如果满足aij=aji(1≤i,j≤n),则称该矩阵为对称矩阵。对称矩阵关于主对角线对称,因此可以压缩存储,节省存储空间。
- 稀疏矩阵:如果矩阵中数值为0的元素数目远远多于非0元素的数目,并且非0元素分布没有规律,则称该矩阵为稀疏矩阵。稀疏矩阵常使用三元组存储法,即存储非零元的同时,存储该元素所对应的行下标和列下标。
经典例题
1. 螺旋矩阵
题目描述 :
给定一个正整数n,生成一个包含1到n^2所有元素,且元素按顺时针顺序螺旋排列的n x n正方形矩阵。
解题思路:
-
使用四个变量表示当前遍历的上下左右边界。
-
按照右、下、左、上的顺序遍历矩阵,每次遍历到边界时更新边界值。
-
当所有元素都被遍历时,结束循环。
#include <vector>
using namespace std;vector<vector<int>> generateMatrix(int n) {
vector<vector<int>> matrix(n, vector<int>(n, 0));
int num = 1, left = 0, right = n - 1, top = 0, bottom = n - 1;while (num <= n * n) { // Traverse right for (int i = left; i <= right && num <= n * n; ++i) { matrix[top][i] = num++; } top++; // Traverse down for (int i = top; i <= bottom && num <= n * n; ++i) { matrix[i][right] = num++; } right--; // If not the last element if (top <= bottom) { // Traverse left for (int i = right; i >= left && num <= n * n; --i) { matrix[bottom][i] = num++; } bottom--; } if (left <= right) { // Traverse up for (int i = bottom; i >= top && num <= n * n; --i) { matrix[i][left] = num++; } left++; } } return matrix;
}
2. 搜索二维矩阵
题目描述 :
编写一个高效的算法来搜索m x n矩阵matrix中的一个目标值target。该矩阵具有以下特性:每行的元素从左到右升序排列;每列的元素从上到下升序排列。
解题思路:
-
从矩阵的右上角或左下角开始搜索。
-
如果当前元素等于目标值,则返回true。
-
如果当前元素大于目标值,向左移动一列。
-
如果当前元素小于目标值,向下移动一行。
#include <vector>
using namespace std;bool searchMatrix(vector<vector<int>>& matrix, int target) {
if (matrix.empty() || matrix[0].empty()) return false;
int rows = matrix.size(), cols = matrix[0].size();
int row = 0, col = cols - 1;while (row < rows && col >= 0) { if (matrix[row][col] == target) return true; else if (matrix[row][col] < target) row++; else col--; } return false;
}
3. 旋转图像
题目描述 :
给定一个n x n的二维矩阵matrix表示一个图像。请你将图像顺时针旋转90度。你必须在原地旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要使用另一个矩阵来旋转图像。
解题思路:
-
先沿主对角线翻转矩阵。
-
再按行翻转矩阵的每一行。
#include <vector>
using namespace std;void rotate(vector<vector<int>>& matrix) {
int n = matrix.size();// Flip along the diagonal for (int i = 0; i < n; ++i) { for (int j = i; j < n; ++j) { swap(matrix[i][j], matrix[j][i]); } } // Flip each row for (int i = 0; i < n; ++i) { for (int j = 0; j < n / 2; ++j