JAVA数据结构与算法
目录
一、 数据结构
1.1 稀疏数组
一:稀疏数组
1.概念:对二维数组进行压缩,即对其二维数组的相同元素的值或0舍去
2.思路:
a.先对二维数组遍历得到非0元素的个数
b.根据非0个数来创建稀疏数组
c.再遍历二维数组将其非0元素压缩进稀疏数组
d.将稀疏数组转为二维数组逆向操作
3.结构:
a.row col value
b.第一行为二维数组的行数和列数;行数为非零个数+1
c.其他行为对应元素在二维数组的位置
4.应用:棋盘,地图
public class SparseArr {
//数组的行数
static final int ROW=11;
//数组的列数
static final int COL=11;
//稀疏数组的列数
static final int SPARSECOL=3;
public static void main(String[] args) {
//创建数组
int[][] arr=new int[ROW][COL];
//数组中1为红子,2为黑子
arr[5][6]=1;
arr[1][2]=2;
arr[3][0]=1;
//打印初始数组
System.out.println("初始数组为:");
printArr(arr);
//遍历初始数组的到非0元素的个数
int num=getNotZero(arr);
System.out.println("非0元素个数为:"+num);
//根据非零元素个数创建稀疏数组
int[][] sparseArr=new int[num+1][SPARSECOL];
//给稀疏数组的第一行赋值:行数,列数,非0个数
sparseArr[0][0]=ROW;
sparseArr[0][1]=COL;
sparseArr[0][2]=num;
//给稀疏数组其他行赋值
int index=1;
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
if (arr[i][j]!=0) {
sparseArr[index][0]=i;
sparseArr[index][1]=j;
sparseArr[index][2]=arr[i][j];
index++;
}
}
}
//打印稀疏数组
System.out.println("稀疏数组:");
printArr(sparseArr);
//将稀疏数组转为二维数组: 第一行构建,后面赋值
int[][] realArr=new int[sparseArr[0][0]][sparseArr[0][1]];
for (int i = 1; i < sparseArr.length; i++) {
realArr[sparseArr[i][0]][sparseArr[i][1]]=sparseArr[i][2];
}
//打印转为二维的数组
System.out.println("稀疏数组转为二维数组:");
printArr(realArr);
}
//打印初始数组
public static void printArr(int[][] arr) {
for (int[] row : arr) {
for (int col : row) {
System.out.printf("%d \t",col);
}
System.out.println();
}
}
//获取初始数组的非零个数
public static int getNotZero(int[][] arr) {
int num=0;
for (int[] row : arr) {
for (int col : row) {
if (col!=0) {
num++;
}
}
}
return num;
}
}
1.2 队列
1.2.1 队列数组实现
一、数组实现队列
1.队列特点:先进先出
2.属性:队列大小,头,尾,存储数组
3.方法:判空,判满,入队(判满),出队(判空),获取头部元素(判空),打印数据
4.存储结构:数组
5.缺陷:其存储空间数组只能用一次,为解决实现环形队列
6.初始化头尾:front为始终指向第一个元素的前一个(位置不包含),rear为当前尾部元素(位置包含)
public class Queue {
public static void main(String[] args) {
// 测试
QueueArr queueArr = new QueueArr(3);
boolean loop = true;
char in;
Scanner input = new Scanner(System.in);
while (loop) {
System.out.println("s(show)打印数据");
System.out.println("h(head)获取头数据");
System.out.println("g(get)出队");
System.out.println("a(add)入队");
System.out.println("e(exit)退出");
System.out.println("=========================");
in=input.next().charAt(0);
switch (in) {
case 's':
queueArr.getQueue();
break;
case 'h':
try {
System.out.println("头数据为:"+queueArr.getHeadElement());
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 'g':
try {
System.out.println("获取数据:"+queueArr.getElement());
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 'a':
int element=input.nextInt();
if (queueArr.addElement(element)) {
}else {
System.out.println("添加失败,队列已经满了~");
}
break;
case 'e':
loop=false;
default:
break;
}
}
}
}
class QueueArr {
// 最大容量
private int maxSize;
// 头
private int front;
// 尾
private int rear;
// 数组存储
private int[] arr;
// 构造方法初始化:传最大容量
public QueueArr(int maxSize) {
this.maxSize = maxSize;
// 构建数组
this.arr = new int[maxSize];
// 初始化头尾:front为始终指向第一个元素的前一个(位置不包含),rear为当前尾部元素(位置包含)
this.front = this.rear = -1;
}
// 判断队列是否为空
public boolean isEmpty() {
return this.front == this.rear;
}
// 判断队列是否已满:容量-1
public boolean isFull() {
return this.rear == this.maxSize - 1;
}
// 出队:获取队列元素
public int getElement() {
// 先判断队列是否为空
if (isEmpty()) {
// 抛异常:不能返回了,返回值可能就为元素值
throw new RuntimeException("队列为空~");
}
// 头部指针发生变化
this.front++;
return this.arr[front];
}
// 入队:添加元素
public boolean addElement(int element) {
// 先判断队列是否已经满了
if (isFull()) {
return false;
}
// 为指针发生变化
this.arr[++rear] = element;
return true;
}
// 获取头部元素:不弹出
public int getHeadElement() {
// 判断队列是否为空
if (isEmpty()) {
throw new RuntimeException("当前队列为空~");
}
return this.arr[front+1];
}
// 显示队列的数据
public void getQueue() {
System.out.print("数据为:");
for (int i = this.front + 1; i <= this.rear; i++) {
System.out.printf("%d\t", this.arr[i]);
}
System.out.println();
}
}
1.2.2 环形队列数组实现
一、数组实现环形队列
1.属性:maxSize(最大个数),front(头),rear(尾),arr(存储结构)
2.注意:
a.front始终指向头元素,rear始终指向尾元素后一个,(头包尾不包)初始 化front=rear=0
b.整个数组始终会预留一个存储空间=>实际大小=maxSize-1
3.方法:
a.判空:front==rear;其数组尾部先动,头跟随尾部而动;当尾从未动或 头跟随动至尾重合即空
b.判满:(rear+1)%maxSize‘==front:其rear是指向尾元素的后一个,其 当队满时rear和front始终会隔一个存储空间
c.入队:判满 => arr[rear]=data => rear=(rear+1)%maxSize
d.出队:判空 => arr[front].out => front=(front+1)%maxsize(跟随尾指针步 伐)
e.取头:判空 => arr[front]
f.打印:判空 => 获元素个数(front+maSize-rear)%maxSize;可分为rear大 于或小于front看待
public class CircleQueueByArr {
public static void main(String[] args) {
CircleQueue queue=new CircleQueue(4);
boolean loop=true;
Scanner input=new Scanner(System.in);
int judge;
int data;
while(loop) {
System.out.println("1:入队");
System.out.println("2:出队");
System.out.println("3:头元素");
System.out.println("4:打印");
System.out.println("5:退出");
judge=input.nextInt();
switch (judge) {
case 1:System.out.print("->要添加的元素值:");
data=input.nextInt();
queue.addData(data);
break;
case 2:System.out.println("->头元素出队:"+queue.outData());
break;
case 3:System.out.println("->获取头元素:"+queue.getHeadData());
break;
case 4:System.out.println("->队列打印结果:");
queue.printQueue();
System.out.println();
break;
case 5:loop=false;
System.out.println("测试完成");
break;
default :break;
}
}
}
}
class CircleQueue {
// 队列大小:但实际大小始终要小1,要预留一个存储空间
private int maxSize;
// 对头:始终指向头一个元素
private int front;
// 队尾:始终指向尾部元素后一个
private int rear;
// 存储结构
private int[] arr;
public CircleQueue(int maxSize) {
this.maxSize = maxSize;
this.arr = new int[maxSize];
}
// 判空
public boolean isEmpty() {
if (this.front == this.rear) {
return true;
}
return false;
}
// 判满
public boolean isFull() {
if ((this.rear + 1) % this.maxSize == front) {
return true;
}
return false;
}
// 入队
public void addData(int data) {
if (!isFull()) {
this.arr[this.rear] = data;
this.rear = (this.rear + 1) % this.maxSize;
System.out.println("-->!入队成功!<--");
return;
}
System.out.println("-->!入队失败!<--");
}
// 出队
public int outData() {
if (!isEmpty()) {
int data = this.arr[this.front];
this.front = (this.front + 1) % this.maxSize;
return data;
} else {
throw new RuntimeException("-->!队列已空,无法取出数据!<--");
}
}
// 获取头元素
public int getHeadData() {
return this.arr[this.front];
}
// 打印队列
public void printQueue() {
int index=front;
//注意front在打印时要变化
for (int i = 0; i < (this.rear+this.maxSize-this.front)%this.maxSize; i++) {
System.out.printf("%d\t", this.arr[index]);
index=(index+1)%this.maxSize;
System.out.println("---"+i);
}
}
}