Java数据结构(一):稀疏数组

目录

稀疏数组的定义

稀疏数组案例

代码实现


稀疏数组的定义

稀疏数组(sparse array)是一种只为数组中的非零元素分配内存的特殊类型数组,内存中存储 了稀疏数组中非零元素的下标和值。可以看做是普通数组的压缩,普通数组是值无效数据量远大于有效数据量的数组。

当一个数组中大部分元素为0,或者为同一个值的数组时,可以使用稀疏数组来保存该数组。

稀疏数组的处理方法是:

1) 记录数组一共有几行几列,有多少个不同的值
2) 把具有不同值的元素的行列及值记录在一个小规模的数组中,从而缩小程序的规模

稀疏数组案例

一个普通二维数组里面存在大量的无效数据的时候,我们可以使用稀疏数组对原数组进行压缩。如下图所示:

代码实现

实现功能一:给出一个普通二维数组,将其压缩为稀疏数组,然后存放到磁盘。

实现功能二:能够从磁盘读取到存在稀疏数组的文件,还原为二维数组。

功能一的代码如下:

package com.chtw.sparsearray;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

public class SparseArrayTest {

	public static void main(String[] args) {
		//定义一个普通二位数组,我们以图片中的数组为例
		int array[][] = new int[7][7];
		
		
		array[1][5] = 9;
		array[2][2] = 5;
		array[4][0] = 7;
		array[5][4] = 4;
		printArray(array);
		
		//先要获取稀疏数组的长度
		int sparseArrayLength = getSparseArrayLength(array);
		
		//定义一个稀疏数组
		int sparseArr[][] = new int[sparseArrayLength][3];
		
		// 第一行,存放数组有多少行,多少列,有多少个非 0 值
		sparseArr[0][0] = array.length;
		sparseArr[0][1] = array[0].length;
		sparseArr[0][2] = sparseArrayLength-1;//非零值就为稀疏数组的长度减一
		
		//将其他值赋值到稀疏数组当中
		fillSparseArray(array, sparseArr);
		System.out.println("==================================================");
		//打印稀疏数组
		printArray(sparseArr);
		
		//保存稀疏数组到本地
		
		try {
			saveSparseArray(sparseArr, "C:\\Users\\CHTW\\Desktop\\");
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}

	/**
	 * 打印数组的方法
	 * @param array
	 */
	public static void printArray(int array[][]) {
		for (int[] row : array) {
			for (int item : row) {
				System.out.printf("%d\t", item);
			}
			System.out.println();
		}
	}
	
	/**
	 * 获取稀疏数组的长度
	 * @param array 原二维数组
	 * @return 稀疏数组的长度
	 */
	public static int getSparseArrayLength(int array[][]) {
		// 1. 计算一共有多少个非零值
		int sum = 0;
		for (int i = 0; i < array.length; i++) {
			for (int j = 0; j < array[i].length; j++) {
				if (array[i][j] != 0)
					sum++;
			}
		}
		return sum+1;
	}
	
	/**
	 * 填充稀疏数组
	 * @param array 原二维数组
	 * @param sparseArr 稀疏数组
	 */
	public static void fillSparseArray(int array[][],int sparseArr[][]) {
		int count = 0;
		for (int i = 0; i < array.length; i++) {
			for (int j = 0; j < array[i].length; j++) {
				if (array[i][j] != 0) {
					count++;
					sparseArr[count][0] = i;
					sparseArr[count][1] = j;
					sparseArr[count][2] = array[i][j];
				}
			}
		}
	}
	
	/**
	 * 保存稀疏数组
	 * @param sparseArr 稀疏数组
	 * @param filePath 文件路径
	 * @throws FileNotFoundException 
	 * @throws IOException 
	 */
	public static void saveSparseArray(int sparseArr[][],String filePath) throws Exception {
		File file = new File(filePath+"sparseArray.txt");
        if(!file.exists()){
            file.createNewFile();
        }
        FileOutputStream fos = new FileOutputStream(file);
        for (int[] row : sparseArr) {
			for (int item : row) {
				fos.write((item+" ").getBytes());
			}
			fos.write("\n".getBytes());
		}
        System.out.println("保存成功");
        fos.flush();
        fos.close();
	}
	
	
}

运行结果如下:

打开保存的文件,文件内容如下:

和我们的稀疏数组保持一致的。

功能二的实现代码如下:添加两个方法即可

    /**
	 * 从文件读取稀疏数组
	 * @param filePath 文件路径
	 * @return
	 */
	public static int[][] readSparseArray(String filePath) throws Exception{
		File file = new File(filePath);
		FileInputStream in = new FileInputStream(file);
		BufferedReader bfr=new BufferedReader(new InputStreamReader(in)); 
		String data=null;
		int count = 0;//计算稀疏数组的长度
		String str="";//读取出来是字符串
		try {
			while((data=bfr.readLine())!=null){
				str += data;
				str += "\n";
				count++;
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		//定义一个int类型的二维数组,来装读取出来的数据
		int sparseArray[][] = new int[count][3];
		
		//按照分行将str分为多组数据
		String strArr1[] = str.split("\n");
		
		//遍历strArr1
		for(int i =0;i<strArr1.length;i++) {
			//同时将二级数组分裂出来
			String strArr2[] = strArr1[i].split(" ");
			
			//遍历strArr2,同时将数据填充到strArr
			for(int j=0;j<strArr2.length;j++) {
				sparseArray[i][j] = Integer.parseInt(strArr2[j]);
			}
			
		}
		
		return sparseArray;
	}
	
	/**
	 * 恢复为原数组
	 * @param sparseArr
	 * @return
	 */
	public static int[][] restoreArray(int sparseArr[][]){
		int chessArr[][] = new int[sparseArr[0][0]][sparseArr[0][1]];
		for (int i = 1; i < sparseArr.length; i++) {
			chessArr[sparseArr[i][0]][sparseArr[i][1]] = sparseArr[i][2];
		}
		return chessArr;
	}

再main函数中添加代码测试:

输出结果为:

和原来的数据是保持一致的。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
做一门精致,全面详细的 java数据结构与算法!!!让天下没有难学的数据结构,让天下没有难学的算法,不吹不黑,我们的讲师及其敬业,可以看到课程视频,课件,代码的录制撰写,都是在深夜,如此用心,其心可鉴,他不掉头发,谁掉头发???总之你知道的,不知道的,我们都讲,并且持续更新,走过路过,不要错过,不敢说是史上最全的课程,怕违反广告法,总而言之,言而总之,这门课你值得拥有,好吃不贵,对于你知识的渴求,我们管够管饱话不多说,牛不多吹,我们要讲的本门课程内容:稀疏数组、单向队列、环形队列、单向链表、双向链表、环形链表、约瑟夫问题、栈、前缀、中缀、后缀表达式、中缀表达式转换为后缀表达式、递归与回溯、迷宫问题、八皇后问题、算法的时间复杂度、冒泡排序、选择排序、插入排序、快速排序、归并排序、希尔排序、基数排序(桶排序)、堆排序、排序速度分析、二分查找、插值查找、斐波那契查找、散列、哈希表、二叉树、二叉树与数组转换、二叉排序树(BST)、AVL树、线索二叉树、赫夫曼树、赫夫曼编码、多路查找树(B树B+树和B*树)、图、图的DFS算法和BFS、程序员常用10大算法、二分查找算法(非递归)、分治算法、动态规划算法、KMP算法、贪心算法、普里姆算法、克鲁斯卡尔算法、迪杰斯特拉算法、弗洛伊德算法马踏棋盘算法。
1.算法是程序的灵魂,优秀的程序在对海量数据处理时,依然保持高速计算,就需要高效的数据结构和算法支撑。2.网上数据结构和算法的课程不少,但存在两个问题:1)授课方式单一,大多是照着代码念一遍,数据结构和算法本身就比较难理解,对基础好的学员来说,还好一点,对基础不好的学生来说,基本上就是听天书了2)说是讲数据结构和算法,但大多是挂羊头卖狗肉,算法讲的很少。 本课程针对上述问题,有针对性的进行了升级 3)授课方式采用图解+算法游戏的方式,让课程生动有趣好理解 4)系统全面的讲解了数据结构和算法, 除常用数据结构和算法外,还包括程序员常用10大算法:二分查找算法(非递归)、分治算法、动态规划算法、KMP算法、贪心算法、普里姆算法、克鲁斯卡尔算法、迪杰斯特拉算法、弗洛伊德算法、马踏棋盘算法。可以解决面试遇到的最短路径、最小生成树、最小连通图、动态规划等问题及衍生出的面试题,让你秒杀其他面试小伙伴3.如果你不想永远都是代码工人,就需要花时间来研究下数据结构和算法。教程内容:本教程是使用Java来讲解数据结构和算法,考虑到数据结构和算法较难,授课采用图解加算法游戏的方式。内容包括: 稀疏数组、单向队列、环形队列、单向链表、双向链表、环形链表、约瑟夫问题、栈、前缀、中缀、后缀表达式、中缀表达式转换为后缀表达式、递归与回溯、迷宫问题、八皇后问题、算法的时间复杂度、冒泡排序、选择排序、插入排序、快速排序、归并排序、希尔排序、基数排序(桶排序)、堆排序、排序速度分析、二分查找、插值查找、斐波那契查找、散列、哈希表、二叉树、二叉树与数组转换、二叉排序树(BST)、AVL树、线索二叉树、赫夫曼树、赫夫曼编码、多路查找树(B树B+树和B*树)、图、图的DFS算法和BFS、程序员常用10大算法、二分查找算法(非递归)、分治算法、动态规划算法、KMP算法、贪心算法、普里姆算法、克鲁斯卡尔算法、迪杰斯特拉算法、弗洛伊德算法马踏棋盘算法。学习目标:通过学习,学员能掌握主流数据结构和算法的实现机制,开阔编程思路,提高优化程序的能力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值