我有一壶酒,足以慰平生。

0%

数据结构与算法再学习

数据结构与算法

数据结构

线性结构

概述

特点:数据元素之间存在一对一的线性关系。

存储结构:顺序存储结构和链式存储结构。

  • 顺序存储结构:顺序存储的线性表称为顺序表,顺序表中存储的元素是连续的。
  • 链式存储结构:链式存储的线性表称为链表,链表中存储的元素不一定是连续的,元素节点中存放数据元素以及相邻元素的地址信息

常见的线性结构

数组、队列、链表、栈。

非线性结构

常见的非线性结构

二维数组、多为数组、广义表、树结构、图结构。

稀疏数组

应用场景

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

稀疏数组的处理方法是

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

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

稀疏数组示例

二维数组和稀疏数组的互相转换

思路

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

    1. 遍历原始的二维数组,得到有效数据的个数sum。
    2. 根据sum就可以创建稀硫数组 sparseArr int【sum+1】【3】。
    3. 将二维数组的有效数据数据存入到稀硫数组。
  • 稀硫数组转原始的二维数组的思路

    1. 先读取稀硫数组的第一行,根据第一行的数据,创建原始的二数组,比如上面的 chessEr2=nt
    2. 在读取稀疏数组后几行的数据,并赋给原始的二维数组即可.

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
package DataStructures.SparseArray;

/**
* @author 李松柏
* @createTime 2020/12/3 9:42
* @description 二维矩阵和稀疏矩阵的互相转化
*/
public class SparseArray {
/**
* 稀疏数组转二维数组
* @param sparseArray 稀疏数组
* @return 二维数组
*/
private static int[][] sparseToArray(int[][] sparseArray) {
int[][] result = new int[sparseArray[0][0]][sparseArray[0][1]];
for (int i = 1; i < sparseArray.length; i++) {
result[sparseArray[i][0]][sparseArray[i][1]] = sparseArray[i][2];
}
return result;
}

/**
* 二维数组转稀疏数组
* @param arr 二维数组
* @return 稀疏数组
*/
private static int[][] toSparseArray(int[][] arr) {
//遍历原始的二维数组,得到有效数据的个数sum。
int sum = 0;
for (int[] ints : arr) {
for (int anInt : ints) {
if (anInt != 0){
sum++;
}
}
}
//根据sum就可以创建稀硫数组 sparseArr int【sum+1】【3】
int[][] sparseArray = new int[sum + 1][3];
//将有效数字存入稀疏矩阵中
sparseArray[0][0]=arr.length;
sparseArray[0][1]=arr[0].length;
sparseArray[0][2]=sum;
int count = 0;
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
if(arr[i][j] != 0){
count++;
sparseArray[count][0] = i;
sparseArray[count][1] = j;
sparseArray[count][2] = arr[i][j];
}
}
}
return sparseArray;
}
}

稀疏数组和二维数组转化

队列

队列介绍

队列是一个有序列表,可以用数组或是链表来实现。

遵循先入先出的原则。即:先存入队列的数据,要先取出。后存入的要后

示意图:(使用数组模拟队列示意图)

image-20201203104145779

数组模拟队列

  • 队列本身是有序列表,若使用数组的结构来存储队列的数据,其中 maxSize是该队列的最大容量

  • 因为队列的输出、输入是分别从前后端来处理,因此需要两个变量front及rear分别记

录队列前后端的下标, front会随看数据输出而改变r,而rear则是随着数据输入而改变。

image-20201203104514772

思路

当我们将数据存入队列时称为” addQueue“, addQueue的处理需要有两个步

骤:

  1. 将尾指针往后移:rea+1,当 front=rear【空】

  2. 若尾指针rear小于队列的最大下标 maxSize-1,则将数据存入rear所指的数

组元素中,否则无法存入数据。rear== maxSize-1【队列满】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
class ArrayQueue {
private int maxSize;//队列最大容量
private int front;//队头
private int rear;//队尾
private int[] arr;//存放数据 模拟队列

//创建队列
public ArrayQueue(int size) {
this.maxSize = size;
this.arr = new int[maxSize];
this.front = -1;//队头元素指向队列首元素的前一个
this.rear = -1;//指向队尾元素
}

//判空
public boolean isEmpty() {
return front == rear;
}

//判满
public boolean isFull() {
return rear == maxSize -1;
}

//入队
public void addQueue(int n){
if(isFull()){
throw new RuntimeException("队列满!");
}else {
arr[++rear] = n;
}
}

//出队
public int getQueue(){
//判空
if(isEmpty()){
throw new RuntimeException("队列空!");
}else {
return arr[++front];
}
}

//显示队列数据
public int[] showQueue() {
if (isEmpty()){
throw new RuntimeException("队列空!");
}else {
return arr;
}
}

//队头元素
public int peek(){
if(isEmpty()){
throw new RuntimeException("队列空!");
}else {
return arr[++front];
}
}
}

缺点:数组只能使用一次,没法复用。

优化:改进成环形队列,取模:%。

数组模拟环形队列思路

参数调整

  1. front:指向队列的首元素。初始值为0
  2. rear:指向队列的最后一个元素。空出一个空间做约定。初始值为0;
  3. 队满:(rear+1)%maxSize == front
  4. 队空: rear==front
  5. 队列中有效数据为 (rear+maxSize-front)%maxSize

代码实现

您的支持是我继续创作的动力