您的位置:首页 > 理论基础 > 数据结构算法

数据结构算法爬坑日记一

2020-08-16 16:02 543 查看

稀疏数组、队列

数据结构分类

线性结构:最常用的数据结构,特点是数据元素之间存在一对一的线性关系
** 分俩种存储结构
** 1.顺序存储结构:又称为顺序表,存储元素是连续的
** 2.链式存储结构:又称为链表,存储元素不一定是连续的,元素节点中存放数据元素以及相邻元素的地址结构
常见线性数据结构:数组、队列、链表、栈

非线性结构:常见二维数组、多维数组、广义表、树、图

稀疏数组(SparseArray)

使用场景:如果一个数组很多元素的值都相同时,使用稀疏数组来保存该数组,缩小存储规模,提高效率
以二维数组转化的稀疏数组为例:第一行为二维数组的总行数、总列数和不为0的数,第二行开始记录每个不为0的
数的具体位置,第一列为行的位置,第二列为列的位置,第三列为具体的值

示例:
需求:五子棋盘映射为一个二维数组,将此二维数组保存到一个稀疏数组内,存入磁盘并读取再转化为二维数组
** 代码实现
public class SparseTest {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//要求:定义一个6*8二维数组,随意存入俩个数据,将此二维数组转换为稀疏数组写入磁盘,读取文件将稀疏数组转换为二维数组
//1.定义初始二维数组
int [][] arr=new int[6][8];
arr[1][2]=1;
arr[2][3]=2;
//2.遍历二维数组获得不为0的项的个数
int sum=0;
for (int[] i : arr) {
for (int j : i) {
if (j != 0) {
sum++;
}
}
}
//定义对应稀疏数组,将二维数组不为0的数据存入
int [][] sparseArr=new int[sum+1][3];
sparseArr[0][0]=arr.length;
sparseArr[0][1]=arr[0].length;
sparseArr[0][2]=sum;
int count=0; // 记录第i个非0数
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
if(arr[i][j]!=0){
count++;
sparseArr[count][0]=i;
sparseArr[count][1]=j;
sparseArr[count][2]=arr[i][j];
}
}
}
//将稀疏数组写入磁盘,采用对象序列化的方式
File file=new File("D:\\1.txt");
ObjectOutputStream out=new ObjectOutputStream(new FileOutputStream(file));
out.writeObject(sparseArr);
out.close();
//从磁盘将稀疏数组反序列化
ObjectInputStream in=new ObjectInputStream(new FileInputStream(file));
int [][] newSparseArr = (int[][]) in.readObject();
//将新的稀疏数组转化为二维数组并验证结果
int [][] newArr=new int[newSparseArr[0][0]][newSparseArr[0][1]];
for (int i = 1; i < sparseArr.length; i++) {
newArr[newSparseArr[i][0]][newSparseArr[i][1]]=newSparseArr[i][2];
}
System.out.println(Arrays.deepToString(newArr));
}
}

队列(Queue)

一种有序列表,可以用数组和链表来实现,特点:先存入的先取出,后存入的后取出

** 示例(数组模拟环形队列)
package myQueue;

//数组模拟环形队列
@SuppressWarnings("all")
public class RoundQueue {
private int maxSize; // 队列长度为max-1
private int front; // 指向队列头部
private int rear; // 指向队列尾部得后一个位置
private int[] arr; // 容器
//初始化队列
public RoundQueue(int max){
maxSize=max;
front=0;
rear=0;
arr=new int[maxSize];
}
//判断队列是否已满
public boolean isFull(){
return (rear+1)%maxSize==front;
}
//判断队列是否为空
public boolean isEmpty(){
return rear==front;
}
//向队列添加数据
public void addRoundQueue(int data){
if(isFull()){
System.out.println("队列已满,无法添加");
return;
}
arr[rear]=data;
rear=(rear+1)%maxSize;
System.out.println("添加了 "+data);
}
//从队列取出数据
public void getRoundQueue(){
if(isEmpty()){
throw new RuntimeException("队列已空,无法取出");
}
int data=arr[front];
front=(front+1)%maxSize;
System.out.println("取出得数据为 "+data);
}
//显示队列全部数据
public void showRoundQueue(){
if(isEmpty()){
throw new RuntimeException("队列已空,无法查看");
}
//循环展示队列数据,从头位置循环到尾部位置
// 因为是环形队列,所以获取下标时需要通过取模进行限制,底层是数组,防止下标越界
// 并且在尾部后一个位置已经到队列尾部的时候,如果数组前面有位置可以存,取模可以将空位移到
//开始位置
for (int i = front; i <front+(rear-front+maxSize)%maxSize ; i++) {
System.out.println("队列内数据 "+arr[i%maxSize]);
}
}
//显示队列头部数据
public void peep(){
if(isEmpty()){
throw new RuntimeException("队列已空,无法查看头数据");
}
System.out.println(arr[front]);
}
}

** 测试
public class QueueTest {
public static void main(String[] args) {
ArrayQueue arrayQueue = new ArrayQueue(3);
boolean flag=true;
while (flag){
System.out.println("s 查看队列数据");
System.out.println("h 查看队列头数据");
System.out.println("a 向队列添加数据");
System.out.println("g 取出队列数据");
System.out.println("e 退出队列");
Scanner scanner = new Scanner(System.in);
switch (scanner.next()){
case "s":
try{
arrayQueue.showQueue();
}catch (Exception e){
System.out.println(e.getMessage());
}
break;
case "h":
try {
arrayQueue.peep();
}catch (Exception e){
System.out.println(e.getMessage());
}
break;
case "a":
System.out.println("请输入添加数据");
arrayQueue.addQueue(scanner.nextInt());
break;
case "g":
try {
arrayQueue.getQueue();
}catch (Exception e){
System.out.println(e.getMessage());
}
break;
case "e":
flag=false;
break;
default:break;
}
}
}
}

** 无法循环重复利用的队列实现(测试同上)
package myQueue;

//数组模拟队列
public class ArrayQueue {
private final int max;
private int front;
private int rear;
private int[] arrQueue;
//初始化队列对象
public ArrayQueue(int maxLength){
max=maxLength;
front=-1;//指向队列头部前一个位置
rear=-1;//指向队列尾部的位置,包含尾部的那个数据
arrQueue=new int[maxLength];
}
//判断队列是否为空
public boolean isEmpty(){
return rear==front;
}
//判断队列是否已满
public boolean isFull(){
return rear==max-1;
}
//向队列内添加数据
public void addQueue(int dada){
if(isFull()){
System.out.println("队列已满");
return;
}
rear++;
arrQueue[rear]=dada;
System.out.println("存入队列数据为 "+dada);
}
//从队列内取出数据
public void getQueue(){
if(isEmpty()){
throw new RuntimeException("队列为空");
}
front++;
System.out.println("取出的数据为 "+arrQueue[front]);
}
//查看队列全部数据
public void showQueue(){
if(isEmpty()){
throw new RuntimeException("队列为空");
}
for (int i : arrQueue) {
System.out.println("队列中的数据为 "+i);
}
}
//查看队列头部数据
public void peep(){
if(isEmpty()){
throw new RuntimeException("队列为空");
}
System.out.println("队列头数据为 "+arrQueue[front+1]);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: