1.基本概念
定义:一个连续的存储单元的有限集合。
数组的主要操作
- 初始化和销毁
- 给出一组下标,检索对应的数组元素
- 给出一组下标,存、取或者修改对应数组元素的值
- 检索满足条件的数组元素
- 升序或者降序排列
- 数组没有插入和删除操作
2.一维数组和二维数组的存储
数组一般采用的顺序存储结构
1.一维数组
若一维数组的每个元素占k个存储单元,并且从I0开始存储数组的第一个元素,则数组的第i个元素的存储位置LOC(ai)为
L
O
C
(
a
i
)
=
L
O
C
(
a
i
)
+
(
i
−
1
)
∗
k
=
I
0
+
(
i
−
1
)
∗
k
LOC(a_i)=LOC(a_i)+(i-1)*k=I_0+(i-1)*k
LOC(ai)=LOC(ai)+(i−1)∗k=I0+(i−1)∗k
2.二维数组
若已知元素 a 11 a_{11} a11的存储地址为 L O C ( a 11 ) LOC(a_{11}) LOC(a11),并且每个元素占用k个存储单元,则数组第i行第j列的元素 a i j a_{ij} aij的存储位置为
按照行序为主序
L
O
C
(
a
i
j
)
=
L
O
C
(
a
11
)
+
(
i
−
1
)
∗
n
∗
k
+
(
j
−
1
)
∗
k
=
L
O
C
(
a
i
j
)
+
[
(
i
−
1
)
∗
n
+
(
j
−
1
)
]
∗
k
LOC(a_{ij})=LOC(a_{11})+(i-1)*n*k+(j-1)*k =LOC(a_{ij})+[(i-1)*n+(j-1)]*k
LOC(aij)=LOC(a11)+(i−1)∗n∗k+(j−1)∗k=LOC(aij)+[(i−1)∗n+(j−1)]∗k
按照列序为主序
L
O
C
(
a
i
j
)
=
L
O
C
(
a
11
)
+
(
j
−
1
)
∗
m
∗
k
+
(
i
−
1
)
∗
k
=
L
O
C
(
a
i
j
)
+
[
(
j
−
1
)
∗
m
+
(
i
−
1
)
]
∗
k
LOC(a_{ij})=LOC(a_{11})+(j-1)*m*k+(i-1)*k =LOC(a_{ij})+[(j-1)*m+(i-1)]*k
LOC(aij)=LOC(a11)+(j−1)∗m∗k+(i−1)∗k=LOC(aij)+[(j−1)∗m+(i−1)]∗k
3.矩阵的压缩存储
1.对称矩阵
矩阵中以主对角线为轴进行对称,存在$ a[i][j] = a[j][i]$ 特点的方阵称之为对称矩阵。
[
1
2
3
4
2
8
5
6
3
5
9
7
4
6
7
10
]
\begin{bmatrix} 1 & 2 & 3 & 4 \\ 2 & 8 & 5 & 6\\ 3 & 5 & 9 & 7\\ 4 & 6 & 7 & 10\\ \end{bmatrix}
⎣⎢⎢⎡12342856359746710⎦⎥⎥⎤
该矩阵对角线上的数字为 1 8 9 10,在对角线两边的元素是对称的,整个矩阵满足
a
[
i
]
[
j
]
=
a
[
j
]
[
i
]
a[i][j] = a[j][i]
a[i][j]=a[j][i]
当我们队该矩阵无压缩存储时,我们需要使用
4
∗
4
4*4
4∗4 = 16个存储空间,但是由于它是对称的,因此我们可以只保存矩阵的上三角或者下三角,这样我们就可以得到整个矩阵模型,而使用的存储空间也会缩小到10。
至此,假设我们拥有一个
n
∗
n
n*n
n∗n的对称矩阵,那么我们只需要
n
∗
(
n
+
1
)
/
2
n*(n+1)/2
n∗(n+1)/2 个存储空间就可以将整个矩阵模型保存下来。
假设我们以下三角元素进行存储,那么则有数组 arr[]
[ 1 2 8 3 5 9 4 6 7 10 ] \begin{bmatrix} 1 & 2 & 8 & 3 & 5 & 9 & 4 & 6 & 7 & 10 \end{bmatrix} [12835946710]
其中:
第一行: 1
第二行: 2 8
第三行: 3 5 9
第四行: 4 6 7 10
对称矩阵压缩完成。
设一维数组
L
T
A
[
0..
n
∗
(
n
+
1
)
/
2
−
1
]
LTA[0..n*(n+1)/2-1]
LTA[0..n∗(n+1)/2−1]作为n阶对称矩阵A的存储结构,那么当A中任意元素
a
[
i
]
[
j
]
a[i][j]
a[i][j]与
L
T
A
[
k
]
LTA[k]
LTA[k]之间存在
k
=
{
i
∗
(
i
−
1
)
/
2
+
j
−
1
i
>
=
j
j
∗
(
j
−
1
)
/
2
+
i
−
1
i
<
j
k=\begin{cases} i*(i-1)/2+j-1 & i>=j \\ j*(j-1)/2+i-1 & i<j \end{cases}
k={i∗(i−1)/2+j−1j∗(j−1)/2+i−1i>=ji<j
2.三角矩阵
[ 1 2 3 4 0 8 5 6 0 0 9 7 0 0 0 10 ] 上 三 角 矩 阵 \begin{bmatrix} 1 & 2 & 3 & 4 \\ 0 & 8 & 5 & 6\\ 0 & 0 & 9 & 7\\ 0 & 0 & 0 & 10\\ \end{bmatrix}\\ 上三角矩阵 ⎣⎢⎢⎡10002800359046710⎦⎥⎥⎤上三角矩阵
[ 1 0 0 0 2 8 0 0 3 5 9 0 4 6 7 10 ] 下 三 角 矩 阵 \begin{bmatrix} 1 & 0 & 0 & 0 \\ 2 & 8 & 0 & 0\\ 3 & 5 & 9 & 0\\ 4 & 6 & 7 & 10\\ \end{bmatrix}\\ 下三角矩阵 ⎣⎢⎢⎡12340856009700010⎦⎥⎥⎤下三角矩阵
所以对于下三角矩阵来讲:
当$ i>=j 时,a[i][j] = arr[i*(i+1)/2+j];当 i<j 时,a[i][j] = 0;$
当我们对上三角矩阵进行压缩时:
当$ i<=j 时, a[i][j] = arr[i*(2*n-i+1)+j-i];当 i>j 时,a[i][j] = 0;$
3.对角矩阵
三对角阵
三对角阵一共由
3
n
−
1
3n-1
3n−1个非零元素
k
=
2
∗
i
+
j
−
3
k=2*i+j-3
k=2∗i+j−3
4.稀疏矩阵
定义
一个较大的矩阵中,零元素的个数相对于整个矩阵元素的总个数所占的比列较大时,可以称该矩阵为一个稀疏矩阵。
三元组表示
代码实现
/**
* 二维数组和稀疏数组的转化
*/
public class spaceArray {
public static void main(String[] args) {
//原始的二维数组
System.out.println("原始的二维数组");
//1.创建一个二维数组11*11
int[][] arr1 = new int[11][11];
//2.对二维数组进行赋值
arr1[1][2] = 3;
arr1[2][3] = 5;
//3.遍历二维数组
for (int[] row : arr1) {
for (int data : row) {
System.out.printf("%d\t",data);
}
System.out.println();
}
//二维数组转换为稀疏数组
System.out.println("二维数组转换为稀疏数组");
//1.获取原始数组中部位零的个数
int sum = 0;
for (int[] row : arr1) {
for (int data : row) {
if (data != 0) {
sum++;
}
}
}
//2.新建一个行为sum+1,列为3的稀疏数组
int[][] arr2 = new int[sum+1][3];
//3.对稀疏数组进行赋值
arr2[0][0] = 11;
arr2[0][1] = 11;
arr2[0][2] = sum;
int i ;
int j ;
int k = 1;
for (i = 0; i < 11; i++) {
for (j = 0; j < 11; j++) {
if (arr1[i][j] != 0) {
arr2[k][0] = i;
arr2[k][1] = j;
arr2[k][2] = arr1[i][j];
k++;
}
}
}
//3.遍历二维数组
for (int[] row : arr2) {
for (int data : row) {
System.out.printf("%d\t",data);
}
System.out.println();
}
//稀疏数组转换为二维数组
System.out.println("稀疏数组转换为二维数组");
//1.根据稀疏数组创建二维数组
int[][] arr3 = new int[arr2[0][0]][arr2[0][1]];
//2.对二维数组进行赋值
for (int i1=1; i1 < sum+1; i1++) {
arr3[arr2[i1][0]][arr2[i1][1]] = arr2[i1][2];
}
//3.遍历二维数组
for (int[] row : arr3) {
for (int data : row) {
System.out.printf("%d\t",data);
}
System.out.println();
}
}
}