线性结构和非线性结构

线性结构和非线性结构

线性结构

1、线性结构作为最常用的数据结构,其特点是数据元素之间存在一对一的线性关系

2、线性结构有两种不同的存储结构,即顺序存储结构(数组)和链式存储结构(链表),顺序存储结构的线性表成为顺序表,顺序表中的存储元素是连续的

3、链式存储的线性表成为链表,链表中的存储元素不一定是连续的,元素节点中存放数据元素以及香菱元素的地址信息。

4、线性结构常见的有:数组、队列、链表和栈。

非线性结构

非线性结构包括:二维数组、多维数组,广义表,树结构,图结构。

一、稀疏数组

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

稀疏数组的处理方法是:

(1)记录数组一共有几行几列,有多少个不同的值

(2)把具有不同值的元素及值记录在一个小规模的数组中,从而缩小程序的规模

原始的二维数组需要存储42个值,而稀疏数组中只需要27(3*(数据值+1 ))个值。

①、二维数组和稀疏数组之间的转换

二维数组转稀疏数组的思路

1、遍历原始的二维数组,得到有效数据的个数sum

2、根据sum就可以创建稀疏数组sparseArr int[sum1]

3、将二维数组的有效数据存入到稀疏数组

稀疏数组转二维数组的思路

1、先读取稀疏数组的第一行,根据第一行的数据,创建原始的二维数组,比如上面的chessArr2 = int[11][11]

2、在读取稀疏数组后几行的数据,并赋给原始的二维数组即可。

②、稀疏数组的代码实现

int[][] chessArray = new int[11][11];

chessArray[1][2] = 1;

chessArray[2][3] = 2;

//将二维数组转稀疏数组的方法

//1.先遍历二维数组 得到非零数据的个数

int sum = 0;

for (int[] row : chessArray ) {

for (int data : row){

if (data != 0){

sum++;

}

}

}

//2.创建对应的稀释数组

int[][] sparseArr = new int[sum+1][3];

//给稀释数组赋值

sparseArr[0][0] = chessArray.length;

sparseArr[0][1] = chessArray[0].length;

sparseArr[0][2] = sum;

//遍历二维数组,得到非零的值和其下标,然后存入稀疏数组

int count = 1;

for (int i = 0; i < chessArray.length; i++) {

for (int j = 0; j < chessArray[i].length; j++) {

if (chessArray[i][j]!=0){

sparseArr[count][0] = i;

sparseArr[count][1] = j;

sparseArr[count][2] = chessArray[i][j];

count++;

}

}

}

//遍历输出稀疏数组

for (int[] row : sparseArr ) {

for (int data : row){

if (data != 0){

System.out.printf("%d\t",data);

}

}

System.out.println();

}

稀疏数组转为二维数组

//创建二维数组

int[][] arr = new int[sparseArr[0][0]][sparseArr[0][1]];

//稀疏数组中的数据存入二维数组

for (int i = 1;i< sparseArr.length;i++){

arr[sparseArr[i][0]][sparseArr[i][1]] = sparseArr[i][2];

}

//输出二维数组

for (int[] i : arr) {

for (int j : i){

System.out.printf("%d\t",j);

}

System.out.println();

}

二、队列

Queue的插入和删除操作在线性表的两端进行,一端允许插入操作,而另一端只允许删除操作,允许插入的一端称为队尾(Rear),允许删除的另一端则称为队头(Front)。队列的插入操作通常称为入队或进队,删除操作通常称为出队。如果队列中没有元素,则称为空队列。

队列是一种只允许在表的前端进行删除操作且在表的后端进行插人操作的线性表。其中,执行插人操作的端叫作队尾,执行删除操作的端叫作队头。没有元素的队列叫作空队列,在队列中插入一个队列元素叫作入队,从队列中删除一个队列元素叫作出队。因为队列只允许在队头插人,在队尾删除,所以最早进入队列的元素将最先从队列中删除,所以队列又叫作先进先出( FIFO-first in first out) 线性表。具体的数据结构如图4-2所示。

队列米缸:上面放米下面取米

用数组模拟队列

要实 一个队列,需要先实现以下核心方法:

add():向队列的尾部加入一个元素(入队),先入队列的元素在最前边

poll():删除队列头部 元素(出队)

peek():取出队列头部的元素。

class CircleArray {

private int maxSize; // 表示数组的最大容量

//front 变量的含义做一个调整: front 就指向队列的第一个元素, 也就是说 arr[front] 就是队列的第一个元素

//front 的初始值 = 0

private int front;

//rear 变量的含义做一个调整:rear 指向队列的最后一个元素的后一个位置. 因为希望空出一个空间做为约定.

//rear 的初始值 = 0

private int rear; // 队列尾

private int[] arr; // 该数据用于存放数据, 模拟队列

public CircleArray(int arrMaxSize) {

maxSize = arrMaxSize;

arr = new int[maxSize];

}

public int[] getArr() {

for (int i = 0; i < arr.length; i++) {

System.out.printf("arr[%d]=%d\n", i, arr[i]);

}

return arr;

}

// 判断队列是否满

public boolean isFull() {

return (rear + 1) % maxSize == front;

}

// 判断队列是否为空

public boolean isEmpty() {

return rear == front;

}

// 添加数据到队列

public void addQueue(int n) {

// 判断队列是否满

if (isFull()) {

System.out.println("队列满,不能加入数据~");

return;

}

//直接将数据加入

arr[rear] = n;

//将 rear 后移, 这里必须考虑取模

rear = (rear + 1) % maxSize;

}

// 获取队列的数据, 出队列

public int getQueue() {

// 判断队列是否空

if (isEmpty()) {

// 通过抛出异常

throw new RuntimeException("队列空,不能取数据");

}

// 这里需要分析出 front是指向队列的第一个元素

// 1. 先把 front 对应的值保留到一个临时变量

// 2. 将 front 后移, 考虑取模

// 3. 将临时保存的变量返回

int value = arr[front];

front = (front + 1) % maxSize;

return value;

}

// 显示队列的所有数据

public void showQueue() {

// 遍历

if (isEmpty()) {

System.out.println("队列空的,没有数据~~");

return;

}

// 思路:从front开始遍历,遍历多少个元素

for (int i = front; i < front + size() ; i++) {

System.out.printf("arr[%d]=%d\n", i % maxSize, arr[i % maxSize]);

}

}

// 求出当前队列有效数据的个数

public int size() {

// rear = 2

// front = 1

// maxSize = 3

return (rear + maxSize - front) % maxSize;

}

// 显示队列的头数据, 注意不是取出数据

public int headQueue() {

// 判断

if (isEmpty()) {

throw new RuntimeException("队列空的,没有数据~~");

}

return arr[front];

}

}