Imagine a 2D int array storing few data and a lot of 0, which are meaningless as default values but still take memory spaces.
Great memory waste right? Sparse array can do the compress job and help you save space.
Sparse array is an alternative way of storing an array, usually used when an array stores a lot of 0 or other repeating values.
The sparse array records 2 things:
- number of rows, columns and valid (non-0) values
- row & col of each non-zero values
An example is:
While the original array on the left takes 42 cells, the sparse array on the right takes 27.
Traverse through the original array to get total number of valid data
sum. Size of sparse array is immutable so this is required to calculate how many rows and cols are needed.Then you can create the sparse array, which should have
sum + 1rows, with an extra top row storing total rows, cols and number of values. Dimension of the array varies number of cols, for 2D array it should be 3.Now store the values with corresponding rows and cols into the sparse array.
Read top row of the sparse array to get number of rows and cols of the original array.
Create the array using the given size and fill with the default value.
Read other rows and assign values to cells.
First we have a 2D int array original with only two valid data:
int[][] original = newint[11][11];
original[1][2] = 1;
original[2][3] = 2;Traverse through original to look for total number of valid data:
intsum = 0;
for (int[] row : original)
{
for (intval : row)
{
if (val != 0) sum++;
}
}Create sparse array using sum:
int[][] sparseArr = newint[sum + 1][3];Assign info of original to top row:
sparseArr[0][0] = original.length;
sparseArr[0][1] = original[0].length;
sparseArr[0][2] = sum;Traverse through original again, this time for assigning values:
intcount = 1; // specifies row in $sparseArrfor (introw = 0 ; row < original.length ; row++)
{
for (intcol = 0 ; col < original[row].length ; col++)
{
intval = original[row][col];
if (val != 0)
{
sparseArr[count][0] = row;
sparseArr[count][1] = col;
sparseArr[count][2] = val;
count++;
}
if (count == sum + 1) break;
// last row reached -> all valid data assigned, no need to continue
}
}Comparison of original array and sparse array:
-- original --
0 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0 0
0 0 0 2 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
-- sparse --
11 11 2
1 2 1
2 3 2
Now convert the sparse back to original array. First read top row to get number of rows and cols of the original array:
introws = sparse[0][0];
intcols = sparse[0][1];Create the array using the given size.
Here the repeating value is 0. As the default value when creating an array, we do not need to deliberately fill in.
int[][] original = newint[rows][cols];Read other rows and assign values to cells:
// skip top rowfor (inti = 1 ; i < sparse.length ; i++)
{
int[] line = sparse[i];
introw = line[0];
intcol = line[1];
intval = line[2];
original[row][col] = val;
}Result of conversion:
0 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0 0
0 0 0 2 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
You can also serialise the sparse array using object stream to save to the disk:
publicstaticvoidserialise(int[][] arr , Stringpath) throwsIOException, FileNotFoundException
{
FileOutputStreamfout = newFileOutputStream(path);
ObjectOutputStreamoout = newObjectOutputStream(fout);
oout.writeObject(arr);
fout.close();
oout.close();
}...and restore it when to use:
publicstaticint[][] deserialise(Stringpath) throwsIOException, FileNotFoundException, ClassNotFoundException
{
FileInputStreamfin = newFileInputStream(path);
ObjectInputStreamoin = newObjectInputStream(fin);
Objectres = oin.readObject();
fin.close();
oin.close();
return (int[][])res;
}