压缩储存
jer2021
2021-01-30 16:33:22
## 数组储存
#### $\color{White}jer$数组一般采用顺序储存结构,因为存储单位元是一维的,而数组可以是多维的,如何用一组连续的储存单位来储存多维数组呢?以二维数组为例,可以按行序储存即先存第一列 ,再存第二列 ,......;
**如果按行序,如何找到$a_{ij}$的存储位置**
$\begin{bmatrix}a_{00}\qquad a_{01}&\cdots\cdots&a_{0n-1}\\\vdots&\ddots&\vdots\\a_{m-1, 0} a_{m-1 ,1}&\cdots&a_{m-1 ,n-1}\end{bmatrix}$
**若表中大多数储存为空则浪费空间,需使用压缩存储的方法减少浪费**
### 知识点概述
1. **什么是压缩存储?**
$\color{White}jer$把多个相同的元素分配一个存储空间 ,元素为0的不分配空间。
2. **什么样的矩阵能够压缩?**
$\color{White}jer$特殊矩阵,如:对称矩阵,对角矩阵 ,三角矩阵,稀疏矩阵等。
3. **什么叫稀疏矩阵?**
$\color{White}jer$矩阵中非零元素的个数较少 ,一般认为非零元素个数小于5%的矩阵为稀疏矩阵。
### 稀疏矩阵的压缩储存
- **三元组法**
![jer](https://cdn.luogu.com.cn/upload/image_hosting/ekhxw4fz.png)
**M由{(1,2,12) ,(1,3,9) ,(3,1,-1) ,(3,6,14) ,(4,3,24) ,5,2,18) ,(6,1,15) ,(6,4,-7)}**
**和矩阵(6,7)唯一确定。**
- 十字链表法
**在十字链表中,矩阵的每一个非零元素用一个结点表示,该结点除了(row ,col ,value)以外,还有两个域:**
- right:用于链接同一行中的下一个非零元素;
- down:用以链接同一列中的下一个非零元素。
**十字链表中结点的结构示意图**
![](https://cdn.luogu.com.cn/upload/image_hosting/cz2i9z93.png)
![](https://cdn.luogu.com.cn/upload/image_hosting/zj0j6qw5.png)
## 集合—并查集
### 1. 概念
**集合是由一个或多个确定的元素所构成的整体集合中的元素。**
**并查集是一个维护集合的数据结构,它能高效支持集合的基本操作。**
$(\mathfrak1)$ $\mathcal{Mack}(\mathcal{x})$ :建立一个新的集合,其仅有的成员(同时就是代表)是 $\mathcal{x}$ 。
由于各集合是分离的,要求$\mathcal{x}$没有在其它集合中出现
$(\mathfrak2)$ $\mathcal{Unionn}(\mathcal{x ,y})$ :合并两个集合
$(\mathfrak3)$ $\mathcal{Find}(\mathcal{x,y})$: 返回一个指向包含$\mathcal{x}$的集合的代表。
**程序清单$\color{White}jer\color{White}jer\color{White}jer$**
**(1)初始化**
```cpp
for(i=1;i<=n;i++)father[i]=i;
```
**(2)寻找根结点**
```cpp
int find(int x){
if(fa[x] != x)fa[x]=find(fa[x]);
return fa[x];
}
```
**(3)合并集合**
```cpp
void unionn(int x ,int y){//合并
x=find(x);y=find(y);
fa[y]=x;
}
```
**(4)检查两个元素是否在一个集合中**
```cpp
bool chk(int x ,int y){
x=find(x);
y=find(y);
if(x == y)return true;
else return false;
}
```
### 经典例题
[P1551亲戚](https://www.luogu.com.cn/problem/P1551)
[P1536村村通](https://www.luogu.com.cn/problem/P1536)
[P3958 [NOIP2017 提高组] 奶酪](https://www.luogu.com.cn/problem/P3958)