数据结构和算法

DSA 主页 DSA 概述 DSA 环境设置 DSA 算法基础 DSA 渐近分析

数据结构

DSA 数据结构基础 DSA 数据结构和类型 DSA 数组数据结构

链接列表

DSA 链接列表数据结构 DSA 双向链接列表数据结构 DSA 循环链表数据结构

堆栈 &队列

DSA 堆栈数据结构 DSA 表达式解析 DSA 队列数据结构

搜索算法

DSA 搜索算法 DSA 线性搜索算法 DSA 二分搜索算法 DSA 插值搜索 DSA 跳跃搜索算法 DSA 指数搜索 DSA 斐波那契搜索 DSA 子列表搜索 DSA 哈希表

排序算法

DSA 排序算法 DSA 冒泡排序算法 DSA 插入排序算法 DSA 选择排序算法 DSA 归并排序算法 DSA 希尔排序算法 DSA 堆排序 DSA 桶排序算法 DSA 计数排序算法 DSA 基数排序算法 DSA 快速排序算法

图形数据结构

DSA 图形数据结构 DSA 深度优先遍历 DSA 广度优先遍历 DSA 生成树

树数据结构

DSA 树数据结构 DSA 树遍历 DSA 二叉搜索树 DSA AVL 树 DSA 红黑树 DSA B树 DSA B+ 树 DSA 伸展树 DSA 尝试 DSA 堆数据结构

递归

DSA 递归算法 DSA 使用递归的汉诺塔 DSA 使用递归的斐波那契数列

分而治之

DSA 分而治之 DSA 最大最小问题 DSA 施特拉森矩阵乘法 DSA Karatsuba 算法

贪婪算法

DSA 贪婪算法 DSA 旅行商问题(贪婪方法) DSA Prim 最小生成树 DSA Kruskal 最小生成树 DSA Dijkstra 最短路径算法 DSA 地图着色算法 DSA 分数背包问题 DSA 作业排序截止日期 DSA 最佳合并模式算法

动态规划

DSA 动态规划 DSA 矩阵链乘法 DSA Floyd Warshall 算法 DSA 0-1 背包问题 DSA 最长公共子序列算法 DSA 旅行商问题(动态方法)

近似算法

DSA 近似算法 DSA 顶点覆盖算法 DSA 集合覆盖问题 DSA 旅行商问题(近似方法)

随机算法

DSA 随机算法 DSA 随机快速排序算法 DSA Karger 最小割算法 DSA Fisher-Yates 洗牌算法

DSA 有用资源

DSA 问答 DSA 快速指南


矩阵或网格数据结构

什么是矩阵数据结构?

矩阵,也称为网格,是一种特殊的二维数组,其中元素按行和列排列。我们也可以说它是一个嵌套在另一个数组中的数组。矩阵的每个元素可以通过行和列索引来标识。

通常,矩阵数据结构用于存储和操作二维结构,例如图形、地图、表格等。它还可用于表示线性方程、变换、旋转和其他数学概念。

Matrix

矩阵的声明和初始化

要声明矩阵,我们只需指定矩阵的数据类型和名称,后跟两个方括号。这两个方括号指定矩阵的行和列。

在所有编程语言中,矩阵的声明和初始化过程非常相似。让我们看一下在各种编程语言中创建矩阵的语法 −

data_type array_name[rows][cols] = {元素以逗号分隔};

在 Python 编程语言中,无需指定数据类型 −

array_name[rows][cols] = {元素以逗号分隔};

矩阵的必要性

矩阵在数学、计算机科学、图形学、机器人技术等众多领域都非常有用。世界各地的公司都以矩阵的形式存储用户信息,这有助于提供推荐和定向营销。

无论是我们最喜欢的电影还是游戏,都是在矩阵计算的帮助下构建的。许多科学创新和研究都直接或间接地需要这些计算。

矩阵表示

我们可以将矩阵数据结构表示为表格形式,其中每个元素存储在单个单元格中。下图展示了矩阵的表示方式 −

矩阵表示

从上图可以看出,− 的以下几个要点:

  • 索引从 0 开始。

  • 一个 5x3 维的矩阵有 15 个元素。

  • 我们可以借助行和列索引来访问或定位任何元素。

矩阵的基本运算

我们可以通过对给定的矩阵数据结构执行各种运算来对其进行操作,例如旋转、加法、乘法等等。

以下是可以对给定矩阵 − 执行的基本运算。

  • 访问 − 访问矩阵的特定行或列。
  • 搜索 − 定位矩阵的特定元素。
  • 排序 − 按特定顺序排列矩阵元素。
  • 插入 − 在指定索引处添加一行。
  • 删除 −从矩阵中删除一行。

矩阵 - 访问操作

在访问操作中,我们打印特定行或列的元素。

算法

以下是访问矩阵 − 元素的算法

1. 开始
2. 声明并初始化矩阵。
3. 访问所需行。
4. 打印结果。
5. 停止

示例

这里,我们看到一个访问操作的实际实现,我们尝试打印一行的元素 −

#include <stdio.h>
int main() {
   // 3x3 矩阵的声明和初始化
   int matrix[3][3] = {{1, 2, 1}, {4, 5, 4}, {7, 8, 7}}; 
   // 访问第二行
   int* rowScnd = matrix[1]; 
   // 循环打印结果
   printf("Accessing a row: ");
   for (int i = 0; i < 3; i++) {
      printf("%d ", rowScnd[i]);
   }
}
#include <iostream>
using namespace std;
int main() {
   // 3x3 矩阵的声明和初始化
   int matrix[3][3] = {{1, 2, 1}, {4, 5, 4}, {7, 8, 7}}; 
   // 访问第二行
   int* rowScnd = matrix[1]; 
   // 循环打印结果
   cout<< "Accessing a row: ";
   for (int i = 0; i < 3; i++) { 
      cout << rowScnd[i] << " "; 
   }
   cout << endl; 
}
import java.util.Arrays;
public class Main {
   public static void main(String[] args) {
      // 3x3 矩阵的声明和初始化
      int matrix[][] = {{1, 2, 1}, {4, 5, 4}, {7, 8, 7}}; 
      // 访问第二行
      int rowScnd[] = matrix[1]; 
      // 打印结果
      System.out.println("Accessing a row: " + Arrays.toString(rowScnd)); 
   }
}
# 3x3 矩阵的声明和初始化
matrix = [[1, 2, 1], [4, 5, 4], [7, 8, 7]] 
# 访问第二行
rowScnd = matrix[1] 
# 打印结果
print("Accessing a row:" )
print(rowScnd) 

输出

Accessing a row: 4 5 4 

矩阵 - 搜索操作

要在给定矩阵中搜索指定元素,我们需要循环遍历每一行和每一列,并将该元素与我们要查找的值进行比较。

算法

以下算法演示了如何搜索给定矩阵 − 的元素。

1. 开始
2. 声明并初始化一个矩阵。
3. 定义目标元素。
4. 使用 for 循环搜索行中的元素。
5. 定义另一个 for 循环搜索列中的元素。
6. 如果找到,返回索引,否则返回 [-1, -1]。
7. 停止

示例

让我们看一个在各种编程语言中搜索操作的实际示例 −

#include <stdio.h>
#include <stdlib.h>
// 搜索元素的函数
int* srchmatrix(int matrix[3][3], int target) {
    // 保存结果的数组
    static int indX[2];
    // 循环遍历每一行
    for (int i = 0; i < 3; i++) {
        // 循环遍历每一列
        for (int j = 0; j < 3; j++) {
            // 将元素与目标元素进行比较
            if (matrix[i][j] == target) {
                // 返回行和列索引
                int* indX = malloc(2 * sizeof(int));
                indX[0] = i;
                indX[1] = j;
                return indX;
            }
        }
    }
    // 如果未找到元素则返回负值
    indX[0] = -1;
    indX[1] = -1;
    return indX;
}
int main() {
    // 3x3 矩阵的声明和初始化
    int matrix[3][3] = {{1, 2, 1}, {4, 5, 4}, {7, 8, 7}};
    // 调用函数
    int* indX = srchmatrix(matrix, 5);
    // 打印结果
    printf("指定元素位于索引: [%d, %d]
", indX[0], indX[1]);
        free(indX);  
    return 0;
}
#include <iostream>
using namespace std;
// 搜索元素的函数
int* srchmatrix(int matrix[3][3], int targtElem) {
   // 保存结果的数组
   static int indX[2];
   // 循环遍历每一行
   for (int i = 0; i < 3; i++) {
      // 循环遍历每一列
      for (int j = 0; j < 3; j++) {
         // 将元素与目标元素进行比较
         if (matrix[i][j] == targtElem) {
            // 返回行和列索引
            indX[0] = i;
            indX[1] = j;
            return indX;
         }
      }
   }
   // 如果未找到元素则返回负值
   indX[0] = -1;
   indX[1] = -1;
   return indX;
}
int main() {
   // 3x3 矩阵的声明和初始化
   int matrix[3][3] = {{1, 2, 1}, {4, 5, 4}, {7, 8, 7}};
   // 调用函数
   int* indX = srchmatrix(matrix, 5);
   // 打印结果
   cout << "指定元素位于索引: [" << indX[0] << ", " << indX[1] << "]" << endl;
   return 0;
}
public class Main {
   // 搜索元素的方法
   public static int[] srchmatrix(int[][] matrix, int targtElem) {
      // 循环遍历每一行
      for (int i = 0; i < matrix.length; i++) {
         // 循环遍历每一列
         for (int j = 0; j < matrix[i].length; j++) {
            // 将该元素与所需元素进行比较
            if (matrix[i][j] == targtElem) {
               // 返回行和列索引
               return new int[]{i, j};
            }
         }
      }
      // 如果未找到元素则返回负值
      return new int[]{-1, -1};
   }
   public static void main(String[] args) {
      // 3x3 矩阵的声明和初始化
      int[][] matrix = {{1, 2, 1}, {4, 5, 4}, {7, 8, 7}};
      // 我们正在寻找的所需元素
      int targtElem = 5;
      // 调用方法 
      int[] indX = srchmatrix(matrix, targtElem);
      // 打印结果
      System.out.println("指定元素位于索引: [" + indX[0] + ", " + indX[1] + "]");
   }
}

# 3x3 矩阵的声明和初始化
matrix = [[1, 2, 1], [4, 5, 4], [7, 8, 7]] 
# 搜索元素的方法
def searchMatrix(matrix, targtElem):
  # 循环遍历每一行
  for i in range(len(matrix)):
    # 循环遍历每一列
    for j in range(len(matrix[i])):
      # 将该元素与所需元素进行比较
      if matrix[i][j] == targtElem:
        # 返回行和列索引
        return (i, j)
  # 如果未找到元素则返回负值
  return (-1, -1)
# 我们正在寻找的所需元素
targtElem = 5
# 调用方法
indX = searchMatrix(matrix, targtElem)
# 打印结果
print(f"指定元素位于索引: {indX}")

输出

指定元素位于索引: [1, 1]

矩阵 - 排序操作

在排序操作中,我们将给定矩阵的元素按指定顺序排列,例如升序或降序。

算法

按升序对矩阵元素进行排序的算法如下 −

1. 开始
2. 声明并初始化矩阵。
3. 比较并排序指定行的每个元素。
4. 打印结果。
5. 停止

示例

在下面的示例中,我们将看到排序操作的实际实现 −

#include <stdio.h>
// 对数组进行排序的函数
void araySort(int mat[], int n) {
   for (int i = 0; i < n-1; i++) {     
      for (int j = 0; j < n-i-1; j++) {
         if (mat[j] > mat[j+1]) {
            // swapping mat[j] and mat[j+1]
            int temp = mat[j];
            mat[j] = mat[j+1];
            mat[j+1] = temp;
         }
      }
   }
}
int main() {
    // 3x4矩阵的声明和初始化
    int matrix[3][4] = {{12, 10, 7, 36}, {20, 9, 8, 4}, {15, 73, 83, 13}};
    // 对第一行进行排序
    araySort(matrix[0], 4);
    // 打印结果
    printf("对第一行进行排序后的矩阵:
");
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 4; j++) {
            printf("%d ", matrix[i][j]);
        }
        printf("
");
    }
    return 0;
}
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
   // 3x4矩阵的声明和初始化
   int matrix[3][4] = {{12, 10, 7, 36}, {20, 9, 8, 4}, {15, 73, 83, 13}};
   // 对第一行进行排序
   sort(matrix[0], matrix[0] + 4);
   // 打印结果
   cout << "对第一行进行排序后的矩阵:" << endl;
   for (int i = 0; i < 3; i++) {
      for (int j = 0; j < 4; j++) {
         cout << matrix[i][j] << " ";
      }
      cout << endl;
   }
   return 0;
}
import java.util.Arrays;
public class Main {
   public static void main(String []args) {
      // 3x4矩阵的声明和初始化
      int[][] matrix = {{12, 10, 7, 36}, {20, 9, 8, 4}, {15, 73, 83, 13}};
      // 对第一行进行排序
      Arrays.sort(matrix[0]);
      // 打印结果
      System.out.println("对第一行进行排序后的矩阵:" );
      for (int i = 0; i < matrix.length; i++) {
         for (int j = 0; j < matrix[i].length; j++) {
            System.out.print(matrix[i][j] + " ");
         }
         System.out.println();
      }
   }
}
# 3x4矩阵的声明和初始化
matrix = [[12, 10, 7, 36], [20, 9, 8, 4], [15, 73, 83, 13]]
# 对第一行进行排序
matrix[0].sort()
# 打印结果
print("对第一行进行排序后的矩阵:")
for row in matrix:
    print(' '.join(map(str, row)))

输出

对第一行进行排序后的矩阵:
7 10 12 36 
20 9 8 4 
15 73 83 13 

矩阵 - 插入操作

在插入操作中,我们在矩阵的指定位置插入一行。

算法

以下是将一行插入给定矩阵第二个位置负号的算法。

1. 开始
2. 声明并初始化一个矩阵。
3. 定义另一个矩阵。
4. 将原矩阵的第一行复制到新矩阵。
5. 在第二个索引处插入所需行。
6. 复制剩余行。
7. 打印结果。
8. 停止

示例

以下示例实际演示了不同编程语言中的插入操作 −

#include <stdio.h>
int main() {
    // 原始矩阵
    int matrix[2][3] = {{19, 14, 21}, {22, 91, 81}};
    // 创建一个包含额外行的新矩阵
    int newmatrix[3][3];
    // 将原始矩阵的第一行复制到新矩阵
    for (int j = 0; j < 3; j++) {
        newmatrix[0][j] = matrix[0][j];
    }
    // 将第二行添加到新矩阵
    int newRow[3] = {53, 63, 73};
    for (int j = 0; j < 3; j++) {
        newmatrix[1][j] = newRow[j];
    }
    // 将原始矩阵的剩余行复制到新矩阵
    for (int i = 2; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            newmatrix[i][j] = matrix[i - 1][j];
        }
    }
    // 打印新矩阵
    printf("添加一行后的新矩阵:
");
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            printf("%d ", newmatrix[i][j]);
        }
        printf("
");
    }
    return 0;
}
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
    // 原始矩阵
    int matrix[2][3] = {{19, 14, 21}, {22, 91, 81}};
    // 创建一个包含额外行的新矩阵
    int newmatrix[3][3];
    // 将原始矩阵的第一行复制到新矩阵
    copy(begin(matrix[0]), end(matrix[0]), begin(newmatrix[0]));
    // 将第二行添加到新矩阵
    int newRow[3] = {53, 63, 73};
    copy(begin(newRow), end(newRow), begin(newmatrix[1]));
    // 将原始矩阵的剩余行复制到新矩阵
    copy(begin(matrix[1]), end(matrix[1]), begin(newmatrix[2]));
    // 打印新矩阵
    cout << "添加一行后的新矩阵:" << endl;
    for (int i = 0; i < 3; i++) {
    for (int j = 0; j < 3; j++) {
      cout << newmatrix[i][j] << ' ';
    }
    cout << '
';
    }
    return 0;
}
import java.util.Arrays;
public class Main {
   public static void main(String[] args) {
    // 原始矩阵
    int[][] matrix = {{19, 14, 21}, {22, 91, 81}};
    // 创建一个包含额外行的新矩阵
    int[][] newmatrix = new int[matrix.length + 1][matrix[0].length];
    // 将原始矩阵的第一行复制到新矩阵
    for (int j = 0; j < matrix[0].length; j++) {
        newmatrix[0][j] = matrix[0][j];
    }
    // 将第二行添加到新矩阵
    int[] newRow = {53, 63, 73};
    for (int j = 0; j < newRow.length; j++) {
        newmatrix[1][j] = newRow[j];
    }
    // 将原始矩阵的剩余行复制到新矩阵
      for (int i = 2; i < newmatrix.length; i++) {
         for (int j = 0; j < matrix[0].length; j++) {
            newmatrix[i][j] = matrix[i - 1][j];
         }
      }
      // 打印新矩阵
      System.out.println("添加一行后的新矩阵:");
      for (int i = 0; i < newmatrix.length; i++) {
         for (int j = 0; j < newmatrix[0].length; j++) {
            System.out.print(newmatrix[i][j] + " ");
         }
         System.out.println();
      }
   }
}
# 原始矩阵
matrix = [[19, 14, 21], [22, 91, 81]]
# 创建一个包含额外行的新矩阵
newmatrix = matrix.copy()
# 向新矩阵添加第二行
newRow = [53, 63, 73]
newmatrix.insert(1, newRow)
# 打印新矩阵
print("添加一行后的新矩阵:")
for row in newmatrix:
    print(' '.join(map(str, row)))

输出

添加一行后的新矩阵:
19 14 21 
53 63 73 
22 91 81 

矩阵 - 删除操作

删除操作会从矩阵中删除特定行。

算法

以下是对给定矩阵 − 执行删除操作的算法

1. 开始
2. 声明并初始化一个矩阵。
3. 定义另一个矩阵。
4. 复制除要删除的行之外的所有元素。
5. 打印新矩阵。
6. 停止

示例

这里,我们看到了一个删除操作的实际实现 −

#include <stdio.h>
// 从矩阵中删除一行的函数
void deleteRow(int mat[3][3], int rowIndex, int rows, int cols) {
    // 创建一个少一行的新矩阵
    int newMat[2][3];
    // 复制除要删除的行之外的所有元素
    int newRow = 0;
    // 循环遍历原始矩阵的行
    for (int i = 0; i < rows; i++) {
        // 跳过要删除的行
        if (i != rowIndex) {
            // 循环遍历原始矩阵的列
            for (int j = 0; j < cols; j++) {
                // 将元素从 mat 复制到 newMat
                newMat[newRow][j] = mat[i][j];
            }
            newRow++; // 增加行索引
        }
    }
    // 打印新矩阵
    printf("删除一行后的新矩阵:
");
    for (int i = 0; i < 2; i++) {
        for (int j = 0; j < cols; j++) {
            printf("%d ", newMat[i][j]);
        }
        printf("
");
    }
}
int main() {
    // 原始矩阵
    int matrix[3][3] = {{19, 14, 21}, {53, 63, 73}, {22, 91, 81}};
    // 删除第一行
    deleteRow(matrix, 0, 3, 3);
    return 0;
}
#include <iostream>
using namespace std;
// 从矩阵中删除一行的函数
void deleteRow(int mat[3][3], int rowIndex, int rows, int cols) {
    // 创建一个少一行的新矩阵
    int newMat[2][3];
    // 复制除要删除的行之外的所有元素
    int newRow = 0;
    // 循环遍历原矩阵的行
    for (int i = 0; i < rows; i++) {
        // 跳过要删除的行
        if (i != rowIndex) {
            // 循环遍历原始矩阵的列
            for (int j = 0; j < cols; j++) {
                // 将元素从 mat 复制到 newMat
                newMat[newRow][j] = mat[i][j];
            }
            newRow++; // 增加行索引
        }
    }
    // 打印新矩阵
    cout << "删除一行后的新矩阵:
";
    for (int i = 0; i < 2; i++) {
        for (int j = 0; j < cols; j++) {
            cout << newMat[i][j] << ' ';
        }
        cout << '
';
    }
}
int main() {
    // 原始矩阵
    int matrix[3][3] = {{19, 14, 21}, {53, 63, 73}, {22, 91, 81}};
    // 删除第一行
    deleteRow(matrix, 0, 3, 3);
    return 0;
}

import java.util.Arrays;
public class Main {
    // 删除行的方法
    public static int[][] deleteRow(int[][] mat, int rowIndex) {
        // 获取行数和列数
        int rows = mat.length;
        int cols = mat[0].length;
        // 创建一个少一行的新矩阵
        int[][] newMat = new int[rows - 1][cols];
        // 复制除要删除的行之外的所有元素
        int newRow = 0;
        // 循环遍历原始矩阵的行
        for (int i = 0; i < rows; i++) { 
            // 跳过要删除的行
            if (i != rowIndex) { 
                // 循环遍历原始矩阵的列
                for (int j = 0; j < cols; j++) { 
                    // 将元素从 mat 复制到 newMat
                    newMat[newRow][j] = mat[i][j]; 
                }
                newRow++; // 增加行索引
            }
        }
        // 返回新矩阵
        return newMat;
    }
    public static void main(String[] args) {
        // 原始矩阵
        int[][] matrix = {{19, 14, 21}, {53, 63, 73}, {22, 91, 81}};
        // 删除第一行
        int[][] newmatrix = deleteRow(matrix, 0);
        // 打印新矩阵
        System.out.println("删除一行后的新矩阵:");
        for (int i = 0; i < newmatrix.length; i++) {
            for (int j = 0; j < newmatrix[0].length; j++) {
                System.out.print(newmatrix[i][j] + " ");
            }
            System.out.println();
        }
    }
}
# 原始矩阵
matrix = [[19, 14, 21], [53, 63, 73], [22, 91, 81]]
# 删除第一行
newmatrix = matrix[1:]
# 打印新矩阵
print("删除一行后的新矩阵:")
for row in newmatrix:
    print(' '.join(map(str, row)))

输出

删除一行后的新矩阵:
53 63 73 
22 91 81