前言
稀疏数组是一种用于表示稀疏数据结构的数据结构。稀疏数组适用于当大部分元素的值为默认值(通常为0或null)时,可以通过压缩存储来节省空间。
稀疏数组通常由三个字段组成:行数、列数和非默认值元素的列表。列表中的每个元素包含非默认值元素的行索引、列索引和值。
稀疏数组的压缩存储方法是将稀疏数组转换为一个二维数组,其中第一行表示原始数组的行数、列数和非默认值元素的个数,接下来的行表示非默认值元素的行索引、列索引和值。这种存储方式可以大大减少空间占用,因为只需要存储非默认值元素的信息。
稀疏数组在处理稀疏矩阵、图等数据结构时非常有用。它可以减少存储空间的需求,提高算法的效率。然而,稀疏数组的操作和访问可能会比普通数组复杂一些,因为需要对稀疏数组进行解压缩和压缩操作。
总之,稀疏数组是一种用于表示稀疏数据结构的数据结构,可以通过压缩存储来节省空间。它在处理稀疏矩阵、图等数据结构时非常有用。
此外,也可以使用链表来保存被压缩后的信息
一、使用二维数组的方式
package exer.SparseArrays;
import javax.swing.*;
import java.util.zip.CheckedOutputStream;
/**
* 稀疏数组的第一行数据分别存入原数组共 几行 几列 有效数值个数
* 后面的几行存入 行索引 列索引 有效数值
*/
public class SparseArray {
public static void main(String[] args) {
//定义原数组
int[][] array=new int[11][11];
array[1][2]=2;
array[2][3]=5;
int num=0;
//遍历原数组
System.out.println("原数组的遍历:");
for (int[]row:array){
for (int arr:row){
if (arr!=0){
//累加有效数值的个数
num++;
}
System.out.printf(arr+"\t");
}
System.out.println();
}
//定义稀疏数组 行数为原数组有效数值+1 列数为3
int[][]sparseArray=new int[num+1][3];
//先将第一行填充数值 表示原数组 几行 几列 有效数值个数
sparseArray[0][0]=11;
sparseArray[0][1]=11;
sparseArray[0][2]=num;
//定义稀疏数组指针,指向要填入的一行
int count=0;
//遍历原数组 将数据存入稀疏数组
for (int i = 0; i < 11; i++) {
for (int j=0;j<11;j++){
if (array[i][j]!=0){
count++;
sparseArray[count][0]=i;
sparseArray[count][1]=j;
sparseArray[count][2]=array[i][j];
}
}
}
//遍历稀疏数组
System.out.println("稀疏数组的遍历:");
for (int[] row:sparseArray){
for (int arr:row){
System.out.printf(arr+"\t");
}
System.out.println();
}
//将稀疏数组还原为原数组
int[][] preArray=new int[sparseArray[0][0]][sparseArray[0][1]];
//遍历稀疏数组 将数组中的值赋给原数组
for (int i = 1; i < num+1; i++) {
preArray[sparseArray[i][0]][sparseArray[i][1]]=sparseArray[i][2];
}
//遍历原数组
System.out.println("遍历还原的数组:");
for (int[]row:preArray){
for (int arr:row){
System.out.printf(arr+"\t");
}
System.out.println();
}
}
}
二、使用链表的方式
package exer.SparseArrays;
/**
* 链表实现稀疏数组
* 创建一个链表类
*/
public class LinkedList {
public int row;
public int col;
public int var;
public LinkedList(int row, int col, int var) {
this.row = row;
this.col = col;
this.var = var;
}
public LinkedList() {
}
public LinkedList next;
}
package exer.SparseArrays;
import javax.swing.*;
public class LinkedSparseArray {
public static LinkedList head = new LinkedList(-1, -1, -1);
public static void main(String[] args) {
//定义原数组
int[][] array = new int[11][11];
array[1][2] = 2;
array[2][3] = 5;
int num = 0;
//遍历原数组
System.out.println("原数组的遍历:");
for (int[] row : array) {
for (int arr : row) {
if (arr != 0) {
//记录有效数据个数
num++;
}
System.out.printf(arr + "\t");
}
System.out.println();
}
//将链表头赋值 填写原数组行数、列数、有效数据个数
head.row = 11;
head.col = 11;
head.var = num;
//定义一个临时节点便于链表的增删改查
LinkedList temp=head;
//遍历原数组将具体数据的信息放入链表中
for (int i = 0; i < 11; i++) {
for (int j = 0; j < 11; j++) {
if (array[i][j]!=0){
temp.next=new LinkedList();
temp.next.row=i;
temp.next.col=j;
temp.next.var=array[i][j];
//进入下一个节点
temp=temp.next;
}
}
}
//遍历链表
temp=head;
System.out.println("链表的遍历:");
while (true){
if (temp==null){
break;
}
System.out.printf(temp.row+"\t"+temp.col+"\t"+ temp.var);
System.out.println();
temp=temp.next;
}
//将链表还原为原数组
int[][] preArray=new int[head.row][head.col];
//遍历链表,将链表中的有效数据赋给原数组
temp=head;
while (true){
if (temp.next==null){
break;
}
preArray[temp.next.row][temp.next.col]=temp.next.var;
temp=temp.next;
}
//遍历原数组
System.out.println("链表还原为原数组后:");
for (int[] row:preArray){
for (int arr:row){
System.out.printf(arr+"\t");
}
System.out.println();
}
}
}