vector之动态二维数组的底层
引言:在计算机编程领域,二维动态数组是一种能够在程序运行期间动态调整其大小的二维数组数据结构。它与静态二维数组的关键区别在于,静态二维数组在编译时就需要确定其大小,而二维动态数组的大小可以在程序运行过程中根据实际需求进行灵活调整。
下面以杨辉三角为例来讲解一下动态二维数组的底层:
// 以杨辉三角的前n行为例:假设n为5 void test2vector(size_t n) {// 使用vector定义二维数组vv,vv中的每个元素都是vector<int>aramae::vector<aramae::vector<int>> vv(n);// 将二维数组每一行中的vecotr<int>中的元素全部设置为1for (size_t i = 0; i < n; ++i)vv[i].resize(i + 1, 1);// 给杨辉三角出第一列和对角线的所有元素赋值for (int i = 2; i < n; ++i){for (int j = 1; j < i; ++j){vv[i][j] = vv[i - 1][j] + vv[i - 1][j - 1];}} }
aramae::vector<aramae::vector<int>> vv(n); 构造一个vv动态二维数组,vv中总共有n个元素,每个元素都是vector类 型的,每行没有包含任何元素,如果n为5时如下所示:
例题:杨辉三角 之内存分配 C/C++
118. 杨辉三角
给定一个非负整数
numRows
,生成「杨辉三角」的前numRows
行。在「杨辉三角」中,每个数是它左上方和右上方的数的和。
示例 1:
输入: numRows = 5 输出: [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]]示例 2:
输入: numRows = 1 输出: [[1]]
1. C 语言实现的动态内存分布
在 C 语言中,杨辉三角通常用二维指针数组实现,内存分配分为两个步骤:
int** generate(int numRows, int* returnSize, int** returnColumnSizes) {// 1. 分配行指针数组int** triangle = (int**)malloc(numRows * sizeof(int*));*returnSize = numRows;*returnColumnSizes = (int*)malloc(numRows * sizeof(int));// 2. 为每行分配元素数组for (int i = 0; i < numRows; i++) {(*returnColumnSizes)[i] = i + 1;triangle[i] = (int*)malloc((i + 1) * sizeof(int));// ... 初始化元素 ...}return triangle;
}
内存布局示意图
triangle指针 行指针数组 每行的元素数组
┌───────┐ ┌───────┐ ┌───────┐
│ 0x100 │─────────▶│ 0x200 │─────────▶│ 1 │ 第0行
└───────┘ ├───────┤ └───────┘│ 0x300 │─────────▶│ 1 │ 第1行├───────┤ ├───────┤│ 0x400 │─────────▶│ 1 │ 第2行├───────┤ ├───────┤│ ... │ │ 2 │└───────┘ ├───────┤│ 1 │└───────┘...
代码实现:
#include <stdio.h> #include <stdlib.h>int** generate(int numRows, int* returnSize, int** returnColumnSizes) {// 分配二维数组的内存,存储杨辉三角的每一行int** triangle = (int**)malloc(numRows * sizeof(int*));*returnSize = numRows;*returnColumnSizes = (int*)malloc(numRows * sizeof(int));for (int i = 0; i < numRows; i++) {// 每一行有i+1个元素(*returnColumnSizes)[i] = i + 1;triangle[i] = (int*)malloc((i + 1) * sizeof(int));// 每行的首尾元素为1triangle[i][0] = 1;triangle[i][i] = 1;// 计算中间元素的值for (int j = 1; j < i; j++) {triangle[i][j] = triangle[i-1][j-1] + triangle[i-1][j];}}return triangle; }int main() {int numRows = 5;int returnSize;int* returnColumnSizes;int** triangle = generate(numRows, &returnSize, &returnColumnSizes);// 打印杨辉三角for (int i = 0; i < returnSize; i++) {for (int j = 0; j < returnColumnSizes[i]; j++) {printf("%d ", triangle[i][j]);}printf("\n");// 释放每行的内存free(triangle[i]);}// 释放二维数组和列大小数组的内存free(triangle);free(returnColumnSizes);return 0; }
2. C++ vector 实现的动态内存分布
C++ 的vector<vector<int>>
实现方式更简洁,但内存布局类似:
vector<vector<int>> generate(int numRows) {vector<vector<int>> triangle(numRows);for (int i = 0; i < numRows; i++) {triangle[i].resize(i + 1);// ... 初始化元素 ...}return triangle;
}
内存布局示意图
triangle对象 外层vector数据 每行的vector数据
┌───────────┐ ┌───────────┐ ┌───────────┐
│ size: 5 │ │ 0x300 │ │ capacity:1│
│ capacity:5│ ├───────────┤ ├───────────┤
│ data:0x200│───────▶│ 0x400 │ │ size:1 │
└───────────┘ ├───────────┤ │ data:0x300││ 0x500 │ └───────────┘├───────────┤ ┌───────────┐│ 0x600 │ │ capacity:2│├───────────┤ ├───────────┤│ 0x700 │ │ size:2 │└───────────┘ │ data:0x400│└───────────┘...
代码实现:
class Solution { public:vector<vector<int>> generate(int numRows) {vector<vector<int>> vv;vv.resize(numRows);for(int i = 0; i < numRows;++i){vv[i].resize(i+1);vv[i][0]= vv[i][i]=1;for(int j = 1;j < i;j++){vv[i][j] = vv[i-1][j-1] + vv[i-1][j];}}return vv;} };