数据结构
数据结构就是存储,组织数据的方式大致分为两类
线性结构和非线性结构
线性结构:常用的数据结构。特点是一对一的线性关系,有两种不同的存储方式顺序存储结构(数组)和链式存储结构(链表)区别在于存储的元素是不是连续的,也就是分配的内存是不是连续的。
非线性结构:树,多维数组,图,广义表
稀疏数组
稀疏数组是为了用更小的空间来存储大量相同数据的二维数组。
稀疏数组是多行三列的二维数组,行数由原二维数组的不同变量个数决定,第一行用来记录原数组一共多上行多少列有多少个不同值,剩下的行都是记录每一个不同值所在的行列和值是多少。
实现方式
//创建的原数组
int[][] arrays = new int[11][11];
arrays[1][2] = 1;
arrays[2][3] = 2;
arrays[2][5] = 1;
//稀疏数组生成方法
public static int[][] getSpareArry(int[][] arry){
int sum = 0 ;//用来记录有多少不同的数据
int count = 1 ;//计数器用来记录稀疏数组的行数
for (int i = 0; i <arry.length ; i++) {
for (int j = 0; j <11 ; j++) {
if (arry[i][j] != 0){
sum = sum +1;
}
}
}
int[][] spareArray=new int[sum +1][3];
spareArray[0][0] = 11 ;
spareArray[0][1] = 11 ;
spareArray[0][2] = sum ;
for (int i = 0; i <arry.length ; i++) {
for (int j = 0; j <11 ; j++) {
if (arry[i][j] != 0){
spareArray[count][0] = i;
spareArray[count][1] = j;
spareArray[count][2] =arry[i][j];
count++;
}
}
}
return spareArray;
}
//稀疏数组转换成原版数组
public static int[][] getArray(int[][] spareArray){
int[][] arrays = new int[spareArray[0][0]][spareArray[0][1]];
for (int i = 1; i <spareArray[0][2]+1 ; i++) {
arrays[spareArray[i][0]][spareArray[i][1]] = spareArray[i][2];
}
return arrays;
}
循环队列
首先我们要认识队列,队列是顺序结构有先进先出的特点简单的队列如图
由一个长度MaxSize的数组和两个指针组成(两个指针就是两个变量)。front指向出口,rear指向入口。每次插入都插入进rear+1的位置,如果rear等于MaxSize-1则达到了最大值队列满,每次取数据就取front+1位置的数据。当front = rear时队列为空。
这样一个队列回出现问题,就是当rear满足rear = MaxSize-1时即使出口有数据取出也无法存入数据,因为条件依然满足。此时我们有两种解决办法,第一种就是每次取数据后将数组整体下移以为rear-1但是这种方式效率很差,所以我们使用第二种方式,当rear已经到数组的边界时如果数组开始的位置没有数据那么就将数据存放到开始的位置也就是使用循环队列。
首先我们也是有MaxSize长的数组 然后front 和rear默认值不再是-1而是0.我们按刚刚的想法来插入完成后rear+1,因为要可以循环使用所以我们采用(rear+1)%MaxSize的增值方式,取出完成后(front+1)%MaxSize但是我们会遇到问题,就是rear=front的情况。当队列为空时它们是相等的,队列满时它们也是相等的,这里我们有两种处理方式来区分。
1.增加判断flage 当flage=0 并且rear=front是队列空,当flage = 1 并且rear=front是队列满。
2.在数组中空一个位置出来用于做判断也就是如图(这种方式队列的长度会比数组长度少一)
这种方式下,当(raer+1)%MaxSize == front时队列是满的(需要取余是因为不知道rear大于front还是小于。所以当raer的下标加上font的下标再加上(数组从0开始的原因)一得到的数是数组的长度的整数倍时,此时队列满)
而这种方式可以求得队列中有几个数据
当rear>front时(左图)长度是rear-front 当rear<front时(右图)长度是 rear 和 MaxSize-front 两个部分 所以通用的公式是(rear-front+MaxSize)%MaxSize
循环队列的实现代码
public class Queue {
private int MixSize;
private int[] queue;
private int font;
private int rear;
//构造方法
public Queue(int mixSize){
MixSize = mixSize+1;
queue = new int[MixSize];
}
//判断队列是否满
public boolean isFull(){
if ((rear +1)%MixSize == font){
return true;
}
return false;
}
//判断是否空
public boolean isNull(){
if (rear == font){
return true;
}
return false;
}
//添加
public void addNum(int num){
if (isFull()){
throw new RuntimeException("队列已满,无法插入");
}
queue[rear] = num;
rear = (rear+1)%MixSize;
}
//取出
public int get(){
if (isNull()){
throw new RuntimeException("队列为空,不能取数据");
}
int num = queue[font];
font = (font+1)%MixSize;
return num;
}
//队列中元素的个数
public int Size(){
if (isNull()){
return 0;
}
return (rear+MixSize-font)%MixSize;
}
}
//测试
public static void main(String[] args) {
Queue queue = new Queue(4);
System.out.println("队列是否为空"+queue.isNull());
queue.addNum(1);
queue.addNum(2);
queue.addNum(3);
queue.addNum(4);
System.out.println("队列数据有:"+queue.Size());
System.out.println("队列是否满:"+queue.isFull());
System.out.println("取队列数:"+queue.get());
System.out.println("取队列数:"+queue.get());
System.out.println("取队列数:"+queue.get());
System.out.println("取队列数:"+queue.get());
}
队列是否为空true
队列数据有:4
队列是否满:true
取队列数:1
取队列数:2
取队列数:3
取队列数:4