数据结构与算法之稀疏数组

目录

1. 数据结构简述

2. 稀疏数组

3. 稀疏数组的压缩。

4. 压缩步骤

5. 稀疏数组压缩的代码实现

6. 稀疏数组的恢复

7. 稀疏数组恢复的代码实现

8. 代码试验


1. 数据结构简述

数据结构是指用来存储数据的结构形式。根据有无分支可以将数据结构分为线性结构和非线性结构。

线性结构常见的有:数组、队列、链表和栈。

线性结构的存储结构有两种:顺序结构和链式结构。

2. 稀疏数组

一个有大量重复值的数组被称为稀疏数组。由于稀疏数组具有大量的重复值,我们可以通过一定的方式来对其进行压缩,使得其保存下来时占用的内存较小。

如下便是一个稀疏数组

0000000080
0020000000
0100000000
0000060000
0000000000
0005000000
0000000000
0000000000
0000000000
0000009000

3. 稀疏数组的压缩。

对于稀疏数组,我们不需要保存所有的值,因为有太多重复的值了。我们只需要将其结构和与大量重复值相异的值及其位置记录下来即可。为此我们可以创建一个新的二维数组,第一行用来保存原有数组的结构,包括行数、列数和需要记录值的个数;剩下行分别用来保存一个值的行值、列值和对应值即可。

需要注意的是,当数组不是稀疏数组时,使用上面的存储方式会使数组占用的内存更大。

4. 压缩步骤

  1. 遍历原有数组,记录需要记录的值的个数。
  2. 创建一个n*3的新数组,第一行保存原有数组的行数、列数和要记录的值的个数。
  3. 重新遍历数组,将需要记录的点的行值、列值和元素值记录到新数组中。

5. 稀疏数组压缩的代码实现

这里给出的是int型二维数组的压缩,其他数组也同理。

    //压缩数组(传入数组和重复值)
	public static int[][] compress(int[][] need,int value){
		//遍历原始数据,记录新数组长度
		int notRepeatNum=1;
		int length=need.length;
		for(int i=0;i<length;i++) {
			for(int j=0;j<length;j++) {
				if(!(need[i][j]==value)) {
					notRepeatNum++;
				}
			}
		}
		//创建新数组
		int [][]newArray=new int[notRepeatNum][3];
		//新数组第一行设置为行数、列数和新数组长度
		int[] objects={length,length,notRepeatNum};
		newArray[0]= objects;
		//遍历原数组,将需要记录的数据记录到新数组中
		int hadRecord=1;
		for(int i=0;i<length;i++) {
			for(int j=0;j<length;j++) {
				if(!(need[i][j]==value)) {
					newArray[hadRecord][0]=i;
					newArray[hadRecord][1]=j;
					newArray[hadRecord][2]=need[i][j];
					hadRecord++;
				}
			}
		}
		//返回新数组
		return newArray;
	}

6. 稀疏数组的恢复

在恢复稀疏数组时,我们要先读取压缩数组的第一行来构建数组的结构。之后再依次遍历稀疏数组,当遍历到压缩数组中记录的位置时,将记录的数值赋值给该位置的元素;如果该位置没有被记录则设置成重复值。

7. 稀疏数组恢复的代码实现

    //恢复数组(传入压缩数组和重复值)
	public static int[][] review(int[][] compressed,int value){
		//读取原数组长度和创建原数组结构
		int length=compressed[0][0];
		int[][] theView=new int[length][length];
		//遍历新数组,如果行索引和压缩数组中未恢复的第一个元素记录的行索引相等
		//则继续判断列索引是否相等,相等则将记录值赋给新数组;如果不相等则所有
		//列都赋值为重复值
		int hadRead=1;
		for(int i=0;i<length;i++) {
			if(compressed[hadRead][0]==i) {
				for(int j=0;j<length;j++) {
					if(compressed[hadRead][0]==i)
					if(compressed[hadRead][1]==j) {
						theView[i][j]=compressed[hadRead][2];
						if(hadRead!=(compressed.length-1))
						hadRead++;
					}
				}
			}else {
				for(int j=0;j<length;j++) {
					theView[i][j]=value;
				}
			}
		}
		//返回新数组
		return theView;
	}

8. 代码试验

试验用的主函数代码如下

public static void main(String[] args) {
	int[][] array= {{0,0,0,0,0,0,8,0,0,0},{0,7,0,0,0,0,0,0,0,0},
			{0,0,0,9,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,5,0},
			{0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0},
			{0,0,1,0,0,0,0,0,0,0},{0,0,2,0,0,0,0,0,9,0},
			{0,0,0,0,0,0,0,0,0,4},{0,2,0,0,0,0,6,0,0,0}};
	System.out.println("原始数组");
	for(int i=0;i<array.length;i++) {
		for(int j=0;j<array.length;j++) {
			System.out.print(array[i][j]);
		}
		System.out.println();
	}
	System.out.println("压缩数组");
	int [][] compressArray=compress(array, 0);
	for(int i=0;i<compressArray.length;i++) {
		for(int j=0;j<3;j++) {
			System.out.print(compressArray[i][j]);
		}
		System.out.println();
	}
	System.out.println("压缩恢复数组");
	array=review(compressArray, 0);
	for(int i=0;i<array.length;i++) {
		for(int j=0;j<array.length;j++) {
			System.out.print(array[i][j]);
		}
		System.out.println();
	}
}

输出结果如下

原始数组
0000008000
0700000000
0009000000
0000000050
0000000000
0000000000
0010000000
0020000090
0000000004
0200006000
压缩数组
101011
068
117
239
385
621
722
789
894
912
966
压缩恢复数组
0000008000
0700000000
0009000000
0000000050
0000000000
0000000000
0010000000
0020000090
0000000004
0200006000

在恢复数组时,读取数据先判断该行是否有被记录,如果没有就直接给这行都赋值为重复值,如果有才逐一判断当前位置是否有被记录。这样在巨型稀疏数组中的效率会比较高。 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值