数据结构(data structure)是计算机存储、组织数据的方式,是相互之间存在一种或多种特定关系的数据元素的集合。要想学习算法,必须要了解数据结构。常见的数据结构有八大类,分别是数组,链表,队列,栈,散列表,树,堆和图,如果细分的话就比较多了,比如堆有最大堆和最小堆,树有红黑树,线段树,哈夫曼树等等,这章我们就来学习他们。
一维数组
数组(Array)是相同数据类型元素的集合所组成的一种线性数据结构,数组在内存中是连续的,他的大小在初始化的时候就已经固定,数组一旦创建,他的长度是不能改变的,我们常见的动态数组 ArrayList 并不是改变了数组的长度,而是又重新创建了一个。我们可以通过数组的下标来访问和修改数组,数组的下标一般都是从 0 开始的,比如数组 a[0] 是数组的第一个元素, a[5] 是数组的第 6 个元素等等,如下图所示。
他的定义如下(这里以 Java 为例)。
// 数组的常见定义方式,长度是3,默认值都是0。
int[] nums1 = new int[3];
// 还可以在定义的时候直接初始化,数组长度是3。
int[] nums2 = {1, 2, 3};
// 还可以这样写。
int[] nums3 = new int[]{1, 2, 3};
// 也可以这样,中括号放到变量的后面。
int nums4[] = {1, 2, 3};
二维数组
如果把一维数组看做一条线,那么二维数组就是一个平面,它类似于数学上的矩阵,如下图所示。
1,矩阵的转置
矩阵转置就是把 m×n 矩阵的行换成同序数的列得到一个 n×m 矩阵,此矩阵叫做原矩阵的转置矩阵,如下图所示。
int[][] transMatrix(int[][] matrix) {
int m = matrix.length, n = matrix[0].length;
int[][] res = new int[n][m];
// 遍历矩阵中的所有元素。
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
res[j][i] = matrix[i][j];// 转置
return res;
}
2,矩阵的加减
矩阵的加法和减法类似,我们这里看一下矩阵的加法,通常的矩阵加法被定义在两个相同大小的矩阵,其内的各元素为其相对应元素相加后的值。
int[][] addMatrix(int[][] matrix1, int[][] matrix2) {
int m = matrix1.length, n = matrix1[0].length;
int[][] res = new int[m][n];
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
res[i][j] = matrix1[i][j] + matrix2[i][j];
return res;
}
3,矩阵乘法
矩阵的乘法比加减要麻烦一些,通常是一个 m*r 的矩阵与一个 r*n 的矩阵相乘,得到的是一个 m*n 的矩阵,计算过程如下图所示。
// matrix1是m*r矩阵,matrix2是r*n矩阵,res为m*n矩阵
int[][] mutMatrix(int[][] matrix1, int[][] matrix2) {
int m = matrix1.length, r = matrix1[0].length, n = matrix2[0].length;
int[][] res = new int[m][n];
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
for (int k = 0; k < r; k++)
res[i][j] += matrix1[i][k] * matrix2[k][j];
return res;
}
除了一维二维数组以外还有三维,四维……。
数组,滚动数组,差分数组,树状数组 | |
链单向表,双向链表,循环链表,跳表,异或链表 | |
队列,循环队列,双端队列 | |
栈 | |
散列表 | |
二叉树,二叉搜索树,AVL树,红黑树,字典树,哈夫曼树,线段树,笛卡尔树 | |
堆 | |
图的介绍,图的遍历,Dijkstra算法,Bellman-Ford算法,SPFA算法,Floyd算法,Prim算法,Kruskal算法,Boruvka算法,拓扑排序 |