完成《数据结构》绪论和栈

main
InkSoul 2023-07-30 17:05:22 +08:00
parent 9c58a966c0
commit 62ccf816fd
11 changed files with 738 additions and 3 deletions

View File

@ -0,0 +1,485 @@
---
title: "《数据结构》栈、队列和数组"
date: 2023-07-30T14:53:00+08:00
---
## 栈
### 逻辑结构知识点
|栈|只允许在一段进行插入或删除操作的线性表|
|---|---|
|栈顶|线性表允许进行插入删除的那一段|
|栈底|线性表允许进行插入删除的那一段|
|操作特性|先进后出|
|数学性质|n个不同元素进栈出栈元素的不同排列的个数为$\frac{1}{n+1}C^n_{2n}$(卡特兰数)
### 存储结构知识点
#### 栈的顺序存储结构
##### 顺序栈的定义
* 采用顺序存储的栈
* 利用一组地址连续的存储单元存放字栈底到栈顶的数据元素
##### 顺序栈的实现
```c
#define Maxsize 50
typedef struct
{
Elemtype data[Maxsize];//存放栈顶元素
int top;//栈顶指针
}SqStack;
```
|栈顶指针|S.top,初始时设置S.top = -1;栈顶元素S.data[S.top]|
|---|---|
|进栈操作|栈不满时栈顶指针先加1再送值到栈顶元素|
|出栈操作|栈非空时先找栈顶元素值再将栈顶指针减1|
|栈空条件|S.top == -1|
|栈满条件|S.top == Maxsize-1;栈长S.top+1|
##### 顺序栈基本运算代码
初始化
```c
Void InitStack(SqStack &S)
{
S.top = -1;
}
```
----
判栈空
```c
bool StackEmpty(SqStack S)
{
if (S.top == -1)//栈空
return true;
else
return false;
}
```
---
进栈
```c
bool Push(SqStack &S,ElemType x)
{
if(S.top == Maxsize -1)//栈满
return false;
S.data[++S.top] = x ;
return true;
}
```
---
出栈
```c
bool Pop(SqStack &S,ElemType x)
{
if(S.top == -1)//栈空
return false;
S.data[S.top--] = x;
return true;
}
```
---
读栈顶元素
```c
bool GetTop(SqStack S,ElemType x)
{
if(S.top==-1)//栈空
return false;
x = S.data[S.top]
return true;
}
```
##### 共享栈
* 定义
* 利用栈底位置相对不变的特性,可让两个顺序栈共享一个一维数组空间
* 将两个栈的栈底分别设置在共享空间的两端,两个栈顶向共享空间的中间延伸
* 特点
* ![](../../images/《数据结构》栈、队列和数组/共享栈特点.jpg)
* 目的
* 更有效地利用存储空间
* 两个栈的空间相互调节,只有在整个存储空间都被占满时才发生上溢
##### 栈的链式存储结构
* 概念
* 采用链式存储的栈
* 优点
* 便于多个栈共享空间和提高其效率,且不存在栈满上溢的情况
* 特点
* 通常采用单链表实现,并规定所有操作都在单链表的表头进行的
* 规定链栈没有头结点Lhead指向栈顶元素
链式栈实现
```c
typedef struct Linknode
{
Elemtype data;//存放栈中元素
struct Linknode *next;//栈顶指针
}* LiStack;
```
### 栈的运算/操作
|InitStack(&S)|初始化栈|初始化一个空栈S|
|---|---|---|
|StackEmpty(S)|判断栈是否为空|空则返回True|
|Push(&S,x)|进栈|若S未满则将x加入使之成为新栈顶|
|Pop(&S,&x)|出栈|若S非空则弹出栈顶元素并用x返回|
|GetTop(S,&x)|读栈顶元素|若栈非空则用x返回栈顶元素|
|DestroyStack(&S)|销毁栈|销毁并释放栈S占用的存储空间|
### 栈的应用
#### 括号匹配
* 初始设置一个空栈,顺序读入括号
* 若是右括号,置于栈顶
* 若是左括号,压入栈中
* 算法结束时,栈为空,否则括号序列不匹配
#### 表达式求值
后缀表达式和正常表达式的相互转换
![](../../images/《数据结构》栈、队列和数组/后缀表达式和正常表达式的相互转换.jpg)
---
中缀到后缀表达式转换的过程
![](../../images/《数据结构》栈、队列和数组/中缀到后缀表达式转换的过程.jpg)
#### 递归
* 在递归调用的过程,系统为每一层的返回点、局部变量、传入实参等开辟了递归工作栈来进行数据存储
* 递归次数过多容易造成栈溢出
* 将递归算法转换为非递归算法,通常需要借助栈来实现这种转换,消除递归不一定需要栈
* 效率不高,原因是递归调用过程中包含很多重复的计算
* 代码简单,容易理解
## 队列
### 逻辑结构知识点
|队列|操作受限的线性表|
|---|---|
|队头|允许删除的一端|
|队尾|允许插入的一端|
|操作特性|先进先出|
### 存储结构知识点
#### 队列的顺序存储结构
##### 顺序队列的定义
* 分配一块连续的存储单元存放队列中的元素
* 设两个指针
* 队头指针front指向队头元素
* 队尾指针rear指向队尾元素的下一个位置
##### 顺序队列的实现
![](../../images/《数据结构》栈、队列和数组/顺序队列的实现.jpg)
```c
#define MaxSize 50
typedef struct
{
ElemType data[MaxSize];
int front,rear;
}SqQueue;
```
|初始状态|Q.front ==Q.rear = 0|
|---|---|
|队满操作|Q.rear == MaxSize不能作为队列满的条件<br>只有一个元素仍满足该条件(假溢出)|
|进队操作|队不满时先送值到队尾元素再将队尾指针加1|
|出队操作|队不空时先取队头元素值再将队头指针加1|
##### 循环队列的定义
* 把存储队列元素的表从逻辑上视为一个环
##### 循环队列的实现
![](../../images/《数据结构》栈、队列和数组/循环队列的实现.jpg)
##### 区分循环队列队空还是队满
||方法一|方法二|方法三|
|---|---|---|---|
|定义|牺牲一个单元来区分队空和队满,入队时少用一个队列单元,约定以队头指针在队尾指针的下一位置为作为队满的标志|类型中增设表示元素个数的数据成员|类型中增设tag数据成员以区分是队满还是队空|
|队空条件|Q.front == Q.rear|Q.size==0|tag=0且因删除导致Q.front == Q.rear|
|队满条件|(Q.rear+1)%MaxSize == Q.front|Q.size == MaxSize|tag=0且因插入导致Q.front==Q.rear|
|元素个数|(Q.rear - Q.front + MaxSize)%MaxSize|||
##### 循环队列的操作代码
初始化
```c
void InitQueue(SqQueue &Q)
{
Q.rear = Q.front =0;
}
```
---
判队空
```c
bool isEmpty(SqQueue Q)
{
if(Q.rear == Q.front)
return true;
else
return false;
}
```
---
入队
```c
bool EnEmpty(SqQueue &Q,ElemType x)
{
if ((Q.rear + 1)% MaxSize == Q.front)
return false;
Q.data[Q.rear] = x;
Q.rear = (Q.rear + 1) % MaxSize;
return true;
}
```
---
出队
```c
bool DeEmpty(SqQueue &Q,ElemType &x)
{
if(Q.rear == Q.front)
return false;
x = Q.data[Q.front];
Q.front = (Q.font + 1) % MaxSize;
return true;
}
```
#### 队列的链式存储结构
##### 链式队列的定义
* 实质是一个同时有队头指针和队尾指针的单链表
* 头指针指向队头结点,尾指针指向队尾结点,即单链表的最后一个节点
* 删除操作时,通常仅需要修改头指针
* 当队列只有一个元素时删除后队列为空修改尾指针为rear = front
##### 链式队列的实现
```c
typedef struct LinkNode
{
ElemType data;
struct LinkNode *next;
}LinkNode;
typedef struct
{
LinkNode * front,*rear;
}LinkNode;
```
##### 链式队列的操作代码
初始化
```c
void InitQueue(LinkQueue &Q)
{
Q.front = Q.rear = (LinkNode *) malloc(sizeof(LinkNode));
Q.front ->next = NULL;
}
```
---
判队空
```c
bool isEmpty(LinkQueue Q)
{
if(Q.rear == Q.front)
return true;
else
return false;
}
```
---
入队
```c
bool EnEmpty(LinkQueue &Q,ElemType x)
{
LinkNode *s = (LinkNode * )malloc(sizeof(LinkNode));
s->data =x;
s->next = NULL;
Q.rear->next =s;
Q.rear = s;
}
```
---
出错
```c
bool DeEmpty(LinkQueue &Q,ElemType &x)
{
if(Q.rear == Q.front)
return false;
LinkNode *p = Q.front->next;
x = p->data;
Q.front->next = p->next;
if(Q.rear == p)
Q.rear = Q.front;
free(p);
return true;
}
```
##### 双端队列
* 定义
* 允许两端都可以进行入队和出队操作的队列
* 将队列的两端分别称为前端和后端
* 特点
* 其元素的逻辑结构仍是线性结构
* 分类
* 输出受限的双端队列
* 允许在一段进行插入和删除,但在另一端只允许插入的双端队列
* 输出固定,看输入
* 输入受限的双端队列
* 允许在一段进行插入和删除,但在另一端只允许删除的双端队列
* 输入固定,看输出
### 队列的运算/操作
|InitQueue(&Q)|初始化队列|构造一个空队列Q|
|---|---|---|
|QueueEmpty(Q)|判队列为空|空则返回True|
|EnQueue(&Q,x)|入队|若队列未满将x加入使之成为新的队尾|
|DeQueue(&Q,&x)|出队|若队列非空删除表头元素并用x返回|
|GetHead(Q,&x)|读队头元素|若队列非空则将队头元素赋值给x|
### 队列的应用
#### 层次遍历
使用队列是为了保存下一步的处理顺序
![](../../images/《计网》应用层/层次域名空间.png)
#### 计算机系统中的应用
* 解决主机与外部设备之间速度不匹配的问题
* 解决由多用户引起的资源竞争问题
* 页面替换算法FIFO算法
## 数组和特殊矩阵
* 重点
* 如何将矩阵更有效地存储在内存中,并能方便地提取矩阵的元素
* 定义
* 由n个相同类型的数据元素构成的有限序列
* 特点
* 数组一旦被定义,其维数和维界就不再改变
* 除结构的初始化和销毁外,数组只会由存取元素和修改元素的操作
* 数组的数据结构
* 一个数组的所有元素在内存中占用一段连续的存储空间
* 多维数组有两种映射方法
* 按行优先
* 先行后列,先存储行号较小的元素,行号相等先存储列好较小的元素
* 按列优先
* 先列后行,先存储列号较小的元素,列号相等先存储行号较小的元素
* 特殊矩阵相关概念
* 压缩存储
* 为多个值相同的元素只分配一个空间,对零元素不分配存储空间,其目的是节省存储空间
* 特殊矩阵
* 具有许多相同矩阵元素或者零元素,并且这些相同矩阵元素或零元素的分布有一定规律性的矩阵
* 常见的特殊矩阵有对称矩阵、三角矩阵第一行和最后一行两个元素其余行3个元素、对角矩阵
* 常考某个值对应的行和列(特殊法代指就好,可用线代知识解决)
* 特殊矩阵的压缩存储方法
* 找到特殊矩阵中值相同的矩阵元素的分布规律
* 把这些呈现规律性分布的、值相同的多个矩阵元素压缩存储到一个存储空间中
* 稀疏矩阵的定义
* 非0元素非常少的矩阵
* 稀疏矩阵的特点
* 稀疏矩阵压缩存储后便失去了随机存取特性
* 可以使用三元组表和十字链表法压缩存储稀疏矩阵

View File

@ -0,0 +1,250 @@
---
title: "《数据结构》绪论"
date: 2023-07-30T10:33:23+08:00
---
## 常考点
* 存储数据时,不仅要存储数据元素的值,还要存储数据元素之间的关系
* 数据的逻辑结构独立于其存储结构
* 循环队列是用顺序表表示的队列,是一种具体的数据结构
* 栈/队列是一种抽象数据结构类型,可采用顺序存储或链式存储,只表示逻辑结构
* 有序表只表示逻辑结构
* 顺序表,哈希表,单链表既描述逻辑结构,又描述存储结构和数据运算
* 可以用抽象数据类型定义一个完整的数据结构
## 数据结构基本概念和术语
* 数据
* 信息的载体
* 数据元素
* 数据的基本单位
* 数据对象
* 具有相同性质的数据元素的集合,是数据的一个子集
* 数据类型
* 一个值的集合和定义在此集合上的一系列操作的总称
* 原子类型
* 其值不可再分的数据类型
* 结构类型
* 其值可以再分解为若干成分的数据类型
* 抽象数据类型
* 抽象数据组织与之相关操作
* 数据结构
* 相互之间存在一种或多种特定关系的数据元素的集合
## 数据结构三要素
### 逻辑结构
* 数据元素之间的逻辑关系,即从逻辑关系上描述数据
* 它与数据的存储无关,是独立于计算机的
* 逻辑结构分为线性结构(线性表、栈、队列)和非线性结构(图、树、集合)
|常见的逻辑结构|数据元素的关系|
|---|---|
|集合|同属一个集合|
|线性结构|一对一|
|树形结构|一对多|
|图状结构或网状结构|多对多|
### 物理结构
* 数据结构在计算机中的表示(映像),也称存储结构
* 包括数据元素的表示和关系的表示
* 是计算机语言实现的饿逻辑结构,依赖于计算机语言
||定义|优点|缺点|
|---|---|---|---|
|顺序结构|按顺序存储|可以实现随机存取<br>每个元素占用很少的存储空间|只能使用相邻的一整块存储单元<br>可能产生较多的外部碎片|
|链式存储|借助指示元素存储地址的指针|不会出现碎片现象<br>能充分使用所有存储单元|每个元素因存储指针而占用额外的存储空间<br>只能实现顺序存取<br>不同节点的存储空间可以不连续<br>同一节点内的存储空间要连续|
|索引存储|建立附加的索引表|检索速度快|附加的索引表额外占用存储空间<br>增加和删除数据时也要修改索引表<br>会花费较多的时间|
|散列存储|根据元素的关键字直接计算出元素的存储地址<br>也叫哈希存储|检索、增加和删除节点的操作都很快|若散列函数不好,则可能出现元素存储单元的冲突<br>解决冲突又会增加时空开销|
### 数据的运算
* 包括运算的定义和实现
* 运算的定义是针对逻辑结构的,指出运算的功能
* 运算的实现是针对存储结构的,指出运算的具体操作步骤
## 算法与算法评价
### 算法基本概念
* 算法
* 对特定问题求解步骤的一种描述,是指令的有限序列,其中的每条指令都代表一个或多个操作
* 重要特性
* 有穷性
* 一个算法必须总在有限步骤后结束,每个步骤可在有限时间内完成
* 确定性
* 算法中每条指令必须有确切的含义,对于相同的输入只能得出相同的输出
* 可行性
* 算法中描述的操作都可以通过已经实现的基本运算执行有限次来实现
* 输入
* 一个算法有零个或多个输入,这些输入取自于某个特定的对象的集合
* 输出
* 一个算法有一个或多个输出,这些输出是与输入有特定关系的量
* 预期目标
* 正确性
* 算法应能正确解决问题
* 可读性
* 以帮助人们理解
* 健壮性
* 输入非法数据时,算法能适当做出反应或进行处理,而不会产生莫名其妙的输出结果
* 高效率与低存储量的需求
* 效率指算法执行的时间,存储量需求指算法执行过程中所需要的最大存储空间,算法应该在保证前面的条件下,执行时间尽可能低存储空间尽可能小
### 算法效率度量
#### 常见时间复杂度
##### 常数阶O(1)
无复杂结构
```c
int i =1;
int j = 2;
++i;
j++;
int m = i+j;
```
##### 对数阶O(logN)
$2^n$次执行后退出循环
```c
int i = 1;
while(i<n)
{
i = i*2;
}
```
##### 线性阶O(n)
常有循环结构
```c
for(i = 1;i<=n;++i)
{
j = i;
j++;
}
```
##### 线性对数阶O(nlogN)
将时间复杂度为O(logN)的代码循环N遍
```c
for(m = 1;m<n;m++)
{
i =1;
while(i<n)
{
i = i*2;
}
}
```
##### O(n * m)
第一层执行m次第二层执行n次共m*n次
```c
for(x =1;i<=m; x++)
{
for ( i= 1;u<= n; i++)
{
j = i;
j++;
}
}
```
##### k次方阶O(n^k)
K层嵌套循环
```c
for( x= 1;i<=n;x++)
{
for( i= 1; i<= n ; i++)
{
j = i;
j++;
}
}
```
#### 常见空间复杂度
##### O(1)
代码中的i、j、m所分配的空间都不随着处理数据量变化
```c
int i = 1;
int j = 2;
++i;
j++;
int m = i + j;
```
##### O(n)
第一行new了一个数组出来这个数据占用的大小为n这段代码的2-6行虽然有循环但没有再分配新的空间
```c
int[] m = new int[n];
for(i = 1; i<=n; ++i)
{
j = i;
j++;
}
```
#### 计算方法
* 求执行次数的贵吗即可
* 先判断退出循环的关系然后构建某语句执行次数和n之间的关系解出的规模就是时间复杂度
![](../../images/《数据结构》绪论/例题1.jpg)
设第k次循环终止
则第k次$(x+1)^2>n$x的初值 = 0第k次时x = k - 1
即$k^2>n,k>\sqrt{n}$
------
![](../../images/《数据结构》绪论/例题2.jpg)
i =1 时, sum = 0+1
i =2, sum = 0+1+2
i =3,sum = 0+1+2+3
sum = 0+1+2+3 +i = $\frac{i(i+1)}{2}$<n
=>i(i+1)<2n$\approx i^2 < n => i< \sqrt{n}$

View File

@ -29,9 +29,9 @@ date: 2023-06-23T21:20:55+08:00
* 数据结构
* 计网
* 3Blue1Brown系列笔记
* [线性代数的本质](https://www.bilibili.com/video/BV1ys411472E/?spm_id_from=333.999.0.0&vd_source=f01c4f943a66795baa8e8524efed8c1e)
* [微积分的本质](https://www.bilibili.com/video/BV1cx411m78R/?spm_id_from=333.999.0.0&vd_source=f01c4f943a66795baa8e8524efed8c1e)
* [深度学习](https://www.bilibili.com/video/BV16x411V7Qg/?spm_id_from=333.999.0.0)
* [线性代数的本质](https://www.bilibili.com/video/BV1ys411472E)
* [微积分的本质](https://www.bilibili.com/video/BV1cx411m78R)
* [深度学习](https://www.bilibili.com/video/BV16x411V7Qg)
* 毕设及后续渲染器编写记录
* c++入门 CS106笔记
* vulkan tutorial 笔记

Binary file not shown.

After

Width:  |  Height:  |  Size: 402 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 250 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 283 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 458 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 KiB