mirror of
https://github.com/142vip/408CSFamily.git
synced 2026-04-14 18:30:30 +08:00
loopQueue ending
This commit is contained in:
56
数据结构/code/LoopQueue.cpp
Normal file
56
数据结构/code/LoopQueue.cpp
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* @Description: 循环队列操作
|
||||
* @Version: Beta1.0
|
||||
* @Author: 【B站&公众号】Rong姐姐好可爱
|
||||
* @Date: 2019-09-27 14:17:28
|
||||
* @LastEditors: 【B站&公众号】Rong姐姐好可爱
|
||||
* @LastEditTime: 2021-03-18 23:52:10
|
||||
*/
|
||||
|
||||
|
||||
|
||||
// 队列最大存储元素个数
|
||||
#define MaxSize 50
|
||||
|
||||
// 结构体定义
|
||||
typedef struct {
|
||||
// 存放队列元素
|
||||
ElemType data[MaxSize];
|
||||
// 队头指针和队尾指针
|
||||
int front,rear;
|
||||
} SqQueue;
|
||||
|
||||
|
||||
|
||||
|
||||
// 入队算法
|
||||
// 尾插法:Q.data[Q.rear]=x;Q.rear=(Q.rear+1)%Maxsize;Q.tag=1
|
||||
// 队空条件:Q.front== Q.rear且Q.tag==0
|
||||
int EnLoopQueue(SqQueue &Q, ElemType x){
|
||||
if(Q.front==Q.rear&&Q.tag==1){
|
||||
return 0;
|
||||
}
|
||||
Q.data[Q.rear]=x;
|
||||
Q.rear=(Q.rear+1)%MaxSize;
|
||||
Q.tag=1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 出队算法
|
||||
// 头结点删除:x=Q.data[Q.front];Q.front=(Q.front +1)%Maxsize;Q.tag=0
|
||||
// 队满条件:Q.front == Q.rear且Q.tag=1
|
||||
// 注意:当删除之后链表为空时,还需增加一步,将尾指针指向头结点
|
||||
int DeLoopQueue(SqQueue &Q, ElemType &x){
|
||||
if (Q.front==Q.rear&&Q.tag==0){
|
||||
return 0;
|
||||
}
|
||||
x=Q.data[Q.front];
|
||||
Q.front=(Q.front+1)%MaxSize;
|
||||
Q.tag=0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
BIN
数据结构/栈和队列/.DS_Store
vendored
BIN
数据结构/栈和队列/.DS_Store
vendored
Binary file not shown.
@@ -4,7 +4,7 @@
|
||||
* @Author: 【B站&公众号】Rong姐姐好可爱
|
||||
* @Date: 2020-03-1 07:23:48
|
||||
* @LastEditors: 【B站&公众号】Rong姐姐好可爱
|
||||
* @LastEditTime: 2021-03-17 23:23:09
|
||||
* @LastEditTime: 2021-03-18 23:51:35
|
||||
-->
|
||||
|
||||
|
||||
@@ -121,13 +121,90 @@ typedef struct {
|
||||
- 队列长度: `(Q.rear+MaxSize-Q.front)%MaxSize`
|
||||
|
||||
|
||||
是不是理解起来有点抽象,其实我最开始学到这里的时候,也不明白为什么要用`除法取余运算(%)`来实现。后来我看看了手机上的时钟指针,一圈两圈三圈的转,好像就开始悟了...
|
||||
> 是不是理解起来有点抽象,其实我最开始学到这里的时候,也不明白为什么要用`除法取余运算(%)`来实现。后来我看看了手机上的时钟指针,一圈两圈三圈的转,好像就开始悟了...其实这种取余操作在计算机知识体系中还是非常常见的,例如:组成原理中将会学到的补码,据说idea就是来源于时钟..
|
||||
|
||||
|
||||
**和时钟一样,顺时钟进行时间变换,在出队、入队时,队首、队尾指针都是按顺时针方向进1**
|
||||
|
||||
|
||||

|
||||
|
||||
如上图,循环队列从最开始初始化为空队列时:`Q.front==Q.rear==0`,经过元素a入队,队尾指针顺时针前移`Q.rear+1`,到元素a、b、c、d陆续入队,就好像时钟转完了一圈,循环队列已满,此时发现:`Q.front==Q.rear==0`在队满时候依然成立,所以结合前面提到的初始化对空条件:`Q.front==Q.rear==0`,用`Q.front==Q.rear`来区分`队空`和`队满`是非常不合适的。
|
||||
|
||||
|
||||
|
||||
|
||||
#### 如何区别队空还是队满
|
||||
|
||||
> 为了很好的区别循环队列的`队空`还是`队满`的情况,一般有三种处理方式.
|
||||
##### 牺牲一个单元来区分队空和队满
|
||||
|
||||
这种方式**要求在入队时少用一个队列单元**,是一种比较普遍的做法。约定:
|
||||
|
||||
**队头指针在队尾指针在队尾指针的下一个位置作为队满标志【重要】**
|
||||
|
||||
- 队满条件:`(Q.rear+1)%MaxSize==Q.front`
|
||||
- 队空条件:`Q.front==Q.rear`
|
||||
- 队列中元素个数:`(Q.rear+MaxSize-Q.front)%MaxSize`
|
||||
|
||||
|
||||
##### 类型中增设表示元素个数的数据成员
|
||||
|
||||
这种就很直接了,直接和MaxSize去比较,就可以有:
|
||||
|
||||
- 队空条件: `Q.count=0`
|
||||
- 队满条件: `Q.count=MaxSize`
|
||||
|
||||
|
||||
值的注意的是:在这个前提下,不论是`队空`还是`队满`,对会存在`Q.front=Q.rear`,这个可以通过前面方案解决。
|
||||
|
||||
##### 类型中增设tag数据成员标记
|
||||
|
||||
通过添加tag标记的方式,区分`队空`还是`队满`
|
||||
|
||||
- `tag==0`的情况下,如果因为删除导致`Q.front==Q.rear`,则队空;
|
||||
- `tag==1`的情况下,如果因为插入导致`Q.front==Q.rear`,则队满;
|
||||
|
||||
可能你会对上面的这两种情况有迷惑,说实话我第一次看的时候,也挺迷惑的,这里我按照我的理解来解释一下:
|
||||
|
||||
> 在循环队列中增加tag数据成员标记,tag的主要作用:
|
||||
> - 在有元素入队的时候,设置tag=1
|
||||
> - 在有元素出队的时候,设置tag=0
|
||||
|
||||
|
||||
对应的算法实现:
|
||||
```C++
|
||||
// 入队算法
|
||||
// 尾插法:Q.data[Q.rear]=x;Q.rear=(Q.rear+1)%Maxsize;Q.tag=1
|
||||
// 队空条件:Q.front== Q.rear且Q.tag==0
|
||||
int EnLoopQueue(SqQueue &Q, ElemType x){
|
||||
if(Q.front==Q.rear&&Q.tag==1){
|
||||
return 0;
|
||||
}
|
||||
Q.data[Q.rear]=x;
|
||||
Q.rear=(Q.rear+1)%MaxSize;
|
||||
Q.tag=1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 出队算法
|
||||
// 头结点删除:x=Q.data[Q.front];Q.front=(Q.front +1)%Maxsize;Q.tag=0
|
||||
// 队满条件:Q.front == Q.rear且Q.tag=1
|
||||
// 注意:当删除之后链表为空时,还需增加一步,将尾指针指向头结点
|
||||
int DeLoopQueue(SqQueue &Q, ElemType &x){
|
||||
if (Q.front==Q.rear&&Q.tag==0){
|
||||
return 0;
|
||||
}
|
||||
x=Q.data[Q.front];
|
||||
Q.front=(Q.front+1)%MaxSize;
|
||||
Q.tag=0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
```
|
||||
#####
|
||||
|
||||
|
||||
### 代码实现
|
||||
@@ -137,8 +214,15 @@ typedef struct {
|
||||
|
||||
|
||||
```C++
|
||||
|
||||
void InitQueque(&Q){
|
||||
/*
|
||||
* @Description: 循环队列初始化,队列为空
|
||||
* @Version: Beta1.0
|
||||
* @Author: 【B站&公众号】Rong姐姐好可爱
|
||||
* @Date: 2019-09-27 14:17:28
|
||||
* @LastEditors: 【B站&公众号】Rong姐姐好可爱
|
||||
* @LastEditTime: 2021-03-18 22:15:06
|
||||
*/
|
||||
void InitLoopQueque(&Q){
|
||||
Q.front=Q.rear=0;
|
||||
}
|
||||
```
|
||||
@@ -146,11 +230,21 @@ void InitQueque(&Q){
|
||||
#### 队列是否为空
|
||||
|
||||
```C++
|
||||
|
||||
bool isEmpaty(Q){
|
||||
/*
|
||||
* @Description: 判断循环队列是否为空
|
||||
* @Version: Beta1.0
|
||||
* @Author: 【B站&公众号】Rong姐姐好可爱
|
||||
* @Date: 2019-09-27 14:17:28
|
||||
* @LastEditors: 【B站&公众号】Rong姐姐好可爱
|
||||
* @LastEditTime: 2021-03-18 22:15:06
|
||||
*/
|
||||
bool isEmpatyLoopQueue(Q){
|
||||
// 注意循环队列对空条件:Q.rear=Q.front
|
||||
if(Q.rear=Q.front){
|
||||
return false;
|
||||
// 队空
|
||||
return true;
|
||||
}else{
|
||||
// 非空
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -158,12 +252,95 @@ bool isEmpaty(Q){
|
||||
```
|
||||
|
||||
|
||||
#### 入队
|
||||
#### 入队操作
|
||||
|
||||
```C++
|
||||
/*
|
||||
* @Description: 循环队列元素入队
|
||||
* @Version: Beta1.0
|
||||
* @Author: 【B站&公众号】Rong姐姐好可爱
|
||||
* @Date: 2019-09-27 14:17:28
|
||||
* @LastEditors: 【B站&公众号】Rong姐姐好可爱
|
||||
* @LastEditTime: 2021-03-18 22:15:06
|
||||
*/
|
||||
bool EnLoopQueue(SqQueue &Q, ElemType x){
|
||||
// 判断循环队列是否已满 注意判断条件:(Q.rear+1)%MaxSize===Q.front
|
||||
if((Q.rear+1)%MaxSize===Q.front){
|
||||
// 循环队列满
|
||||
return false;
|
||||
}
|
||||
// 队列未满,可进行入队操作【队尾进行】
|
||||
|
||||
// 队尾指针指向的数据域进行赋值
|
||||
Q.data[Q.rear]=x;
|
||||
|
||||
bool EnSqQueue(SqQueue)
|
||||
//队尾指针后移+1【类似时钟的顺时针方向】
|
||||
Q.rear=((Q.rear+1)%MaxSize);
|
||||
|
||||
// 入队成功,返回true
|
||||
return true;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
#### 出队
|
||||
#### 出队操作
|
||||
|
||||
|
||||
```C++
|
||||
|
||||
/*
|
||||
* @Description: 循环队列元素出队
|
||||
* @Version: Beta1.0
|
||||
* @Author: 【B站&公众号】Rong姐姐好可爱
|
||||
* @Date: 2019-09-27 14:17:28
|
||||
* @LastEditors: 【B站&公众号】Rong姐姐好可爱
|
||||
* @LastEditTime: 2021-03-18 20:32:18
|
||||
*/
|
||||
bool DeLoopQueue(SqQueue &Q, ElemType &x){
|
||||
|
||||
// 判断循环队列是否为空队列
|
||||
if(Q.rear==Q.front){
|
||||
|
||||
// 队列为空,无法进行出队操作,返回false
|
||||
return false;
|
||||
}
|
||||
|
||||
// 循环队列非空,元素可出队【队首操作】
|
||||
|
||||
// 将循环队列队首指针指向的元素的数据域赋值给变量x
|
||||
x=Q.data[Q.front];
|
||||
|
||||
// 移动队首指针,顺时针后移+1
|
||||
Q.front=(Q.front+1)%MaxSize;
|
||||
|
||||
// 出队成功,返回true
|
||||
return true;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
#### 获取队头元素
|
||||
|
||||
```C++
|
||||
/*
|
||||
* @Description: 获取循环队列队头元素
|
||||
* @Version: Beta1.0
|
||||
* @Author: 【B站&公众号】Rong姐姐好可爱
|
||||
* @Date: 2019-09-27 14:17:28
|
||||
* @LastEditors: 【B站&公众号】Rong姐姐好可爱
|
||||
* @LastEditTime: 2021-03-18 20:15:33
|
||||
*/
|
||||
bool GetLoopQueueHead(SqQueue &Q, ElemType &x){
|
||||
// 判断循环队列是否为空队列
|
||||
if(Q.front==Q.rear){
|
||||
// 队列为空,没有队头元素,返回false
|
||||
return false;
|
||||
}else{
|
||||
// 获取队头指针指向元素的数据域,赋值给x
|
||||
x=Q.data[Q.front];
|
||||
|
||||
// 获取队头元素成功,返回true
|
||||
return true;
|
||||
}
|
||||
}
|
||||
```
|
||||
BIN
数据结构/栈和队列/images/循环队列入队.png
Normal file
BIN
数据结构/栈和队列/images/循环队列入队.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 54 KiB |
Reference in New Issue
Block a user