SparseArray& CircularQueue
数据结构
- 数据结构分为2种, 线性结构和非线性结构
- 线性结构
(1) 数据元素之间是一对一的线性关系. 常见有数组, 队列, 链表和栈等
(2) 存储结构有两种:
- 顺序存储结构: 顺序存储的线性表称为顺序表, 顺序表中的存储元素是连续的
- 链式存储结构: 链式存储的线性表称为链表, 链表中的存储元素不一定是连续的(元素节点中存放的数据包括:元素和相邻元素的地址), 所以链式存储结构可以利用内存碎片空间来存储数据
- 非线性结构
(-) 数据元素之间不是一对一的关系. 常见有二维数组, 多维数组, 广义表, 树结构, 图结构等
稀疏数组(Sparse Array)
- 当一个数组中大部分元素为0或者同一个相同的值时, 便可以使用稀疏数组
- 稀疏数组的元素结构:
- 记录指定数组一共有几行几列及有多少个不同的值(有效值)
- 将具有不同值的元素的行列及值记录在一个小规模的数组中, 从而缩小数据来达到压缩的目的(压缩后的数据可用于存取等功能)
- 二维数组(原始数据)转换稀疏数组的思路:
- 遍历原数组, 获取有效值个数 sum
- 根据 sum, 锁定稀疏数组的行数 int sparseArr[][] = new int[sum + 1][3]; 其中+1是因为多一行用于记录原数组的行列及有效值个数
- 将有效值存到稀疏数组
- 稀疏数组转换原数组的思路:
- 读取稀疏数组的第一行, 创建原数组 int[][] chessArr2 = new int[sparseArr[0][0]][sparseArr[0][1]];
- 再将稀疏数组的其它数据, 赋值给原数组 chessArr2
- 实例代码:
public class SparseArrayApp {
public static void main(String[] args) {
/** 锁定原数组的行数与列数*/
int rows = 4;
int columns = 5;
/** 创建二维数组(原始数据)*/
int[][] chessArray1 = new int[rows][columns];
/** 原数据, 插入几个有效值*/
chessArray1[1][1] = 1;
chessArray1[1][2] = 2;
chessArray1[2][2] = 4;
/** 输出原数组*/
System.out.println("原数组:");
for (int[] row : chessArray1) {
for (int data : row) {
System.out.print(data + " ");
}
System.out.println();
}
/** 1. 遍历原数组, 获取有效值个数 sum*/
int sum = 0;
for (int i = 0; i < chessArray1.length; i++) {
for (int j = 0; j < chessArray1[i].length; j++) {
if (chessArray1[i][j] != 0) {
sum++;
}
}
}
System.out.println("有效值个数: " + sum);
System.out.println();
/** 2. 根据 sum, 创建稀疏数组*/
int sparseArr[][] = new int[sum + 1][3];
/** 第一行设定原数组的行数列数及有效值个数*/
sparseArr[0][0] = rows;
sparseArr[0][1] = columns;
sparseArr[0][2] = sum;
/** 遍历二维数组,将非0的值存放到稀疏数组中*/
int count = 0;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
if (chessArray1[i][j] != 0) {
count++;
sparseArr[count][0] = i;
sparseArr[count][1] = j;
sparseArr[count][2] = chessArray1[i][j];
}
}
}
/** 输出稀疏数组的存储形式*/
System.out.println("稀疏数组:");
for (int i = 0; i < sparseArr.length; i++) {
System.out.printf("%d\t%d\t%d\t\n", sparseArr[i][0], sparseArr[i][1], sparseArr[i][2]);
}
/** 稀疏数组转换原数组*/
/** 1. 读取稀疏数组的第一行, 创建原数组*/
int[][] chessArr2 = new int[sparseArr[0][0]][sparseArr[0][1]];
/** 2. 再将稀疏数组的其它数据, 赋值给原数组 chessArr2*/
for (int i = 1; i < sparseArr.length; i++) {
chessArr2[sparseArr[i][0]][sparseArr[i][1]] = sparseArr[i][2];
}
/** 输出新创建的原数组 chessArr2*/
System.out.println();
System.out.println("新的原数组:");
for (int[] row : chessArr2) {
for (int data : row) {
System.out.print(data + " ");
}
System.out.println();
}
}
}
> 原数组:
> 0 0 0 0 0
> 0 1 2 0 0
> 0 0 4 0 0
> 0 0 0 0 0
> 有效值个数: 3
>
> 稀疏数组:
> 4 5 3
> 1 1 1
> 1 2 2
> 2 2 4
>
> 新的原数组:
> 0 0 0 0 0
> 0 1 2 0 0
> 0 0 4 0 0
> 0 0 0 0 0
环形队列(CircularQueue)
- 遵循先入先出的原则, 所谓环形意思为用过的元素可以重复使用
- front指向队列的第一个元素, 初始值为0
- rear指向队列的最后一个元素的后一个位置, 此元素不为存值. rear的初始值为0
- 队列满的条件:
(rear + 1) % maxSize == front
- 队列空的条件:
rear == front
- 队列中的有效数据个数:
(rear + maxSize - front) % maxSize
- 实例代码:
public class CircularQueueApp {
public static void main(String[] args) {
System.out.println("s(show): 显示队列");
System.out.println("e(exit): 退出队列");
System.out.println("a(add): 添加数据到队列");
System.out.println("g(get): 从队列中取出数据");
System.out.println("h(head): 查看队列头的数据");
/** 创建长度为3的环形队列*/
CircularQueue circularQueue = new CircularQueue(3);
Scanner sc = new Scanner(System.in);
boolean bLoop = true;
while (bLoop) {
String next = sc.next();
switch (next) {
case "s":
circularQueue.showQueue();
break;
case "a":
System.out.println("请输入一个数值");
int i = sc.nextInt();
circularQueue.addQueue(i);
break;
case "g":
try {
int res = circularQueue.removeQueue();
System.out.println("取出的数据是 " + res);
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case "h":
try {
int res = circularQueue.headQueue();
System.out.println("队列头数据是 " + res);
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case "e":
sc.close();
bLoop = false;
break;
}
}
System.out.println("程序退出");
}
}
class CircularQueue {
private int front;
private int rear;
private int maxSize;
private int arr[];
public CircularQueue(int maxSize) {
this.maxSize = maxSize;
arr = new int[maxSize];
}
public boolean isFull() {
return (rear + 1) % maxSize == front;
}
public boolean isEmpty() {
return rear == front;
}
public void addQueue(int value) {
if (isFull()) {
System.out.println("队列为满,不能添加");
return;
}
arr[rear] = value;
rear = (rear + 1) % maxSize;
}
public int removeQueue() throws Exception {
if (isEmpty()) {
throw new Exception("队列为空,没有可以取的数据");
}
int value = arr[front];
front = (front + 1) % maxSize;
return value;
}
public void showQueue() {
if (isEmpty()) {
System.out.println("队列为空, 没有数据");
}
int len = front + ((rear + maxSize - front) % maxSize);
for (int i = front; i < len; i++) {
System.out.printf("arr[%d]=%d\n", i % maxSize, arr[i % maxSize]);
}
}
public int headQueue() throws Exception {
if (isEmpty()) {
throw new Exception("队列为空, 没有数据");
}
return arr[front];
}
}
如果您觉得有帮助,欢迎点赞哦 ~ 谢谢!!