C/C++语言数据结构快速入门(代码解析+内容解析)队列
Posted 蓝盒子bluebox
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C/C++语言数据结构快速入门(代码解析+内容解析)队列相关的知识,希望对你有一定的参考价值。
一、队列的基本概念
注:数据结构三要素–逻辑结构,数据的运算,存储结构(物理结构)
存储结构不同,运算的实现方式也不同
1、队列的定义
线性表是具有相同数据类型的n(n>=0)个数据元素的有限序列,其中n为表长,当n=0的时候线性表是一个空表。若用L命名线性表,则其一般表示为
栈(Stack)是只允许在一端进行插入(进栈)或删除(出栈)操作的线性表
队列(Queue)是只允许在一端进行插入(入队),在另外一端进行删除(出队)的线性表
队列(Queue)是只允许在一端进行插入,在另外一端删除的线性表
特点:先进入队列的元素先出对
主要术语:
队头、队尾、空队列
2、队列的基本操作
InitQueue(&Q);
初始化队列,构造一个空队列Q。(创)
DestoryQueue(&Q);
销毁队列。销毁并释放队列Q。(销)
EnQueue(&Q,x);
入队,若队列Q未满,将x加入,使只成为新的队尾。(增)
(删除队头元素)DeQueue(&Q,&x);
出队,若队列Q非空,删除对头元素,并用x返回。(删)
(不删除对头元素)GetHead(Q,&x);
读队头元素,若队列Q非空,则将对头元素赋值给x。(查:队列的使用场景当中大多数只能访问对头元素)
二、队列的操作
1、队列的顺序实现
#define MaxSize 10 //定义队列中元素的最大值
typedef struct {
ElemType data[MaxSize]; //用静态数组存放队列元素
int front,rear;
}SqQuenue;
Sq:sequence—顺序
连续的存储空间,大小MaxSize*sizeof(ElemType)
void testQueue(){
SqQueue Q;//声明一个队列(顺序存储)
//...后续操作...
}
2、初始化操作
#include<stdio.h>
#define MaxSize 10 //定义队列中元素的最大个数
typedef struct{
ElemType data[MaxSize]; //用静态数组存放队列元素
int front,rear; //对头指针和队尾指针
}SqQueue;
//初始化队列
void InitQueue(SqQueue &Q){
//初始时 对头 队尾指针指向Q
Q.rear = Q.front = 0;
}
void testQueue(){
//声明一个队列(顺序存储)
SqQueue Q;
InitQueue(Q);
//...后续操作...
}
//判断队列是否为空
bool QueueEmpty(SqQueue Q){
if(Q.rear == Q.front) //队空条件
return true;
else
return false;
}
3、入队操作(只能从队尾入队)(插入)
#define MaxSize 10
typedef struct{
ElemType data[MaxSize];
int front,rear;
}SqQueue;
//入队
bool EnQueue(SqQueue &Q,ElemType x){
if(队列已满)
return false;//队满则报错
Q.data[Q.rear] = x;//将x插入队尾
Q.rear=Q.rear + 1;//队尾指针后移
return true;
}
(1)插入一个元素
插入多个元素
当队尾rear==MaxSize???的时候,此时队列并没有存满
因为front端可能会出队
当rear指向最后一个位置的元素的时候
如果此时front不在头结点的位置,
rear会回到头结点报错新插入的元素到头结点
(2)入队操作的改进版
#include<stdio.h>
#define MaxSize 10 //定义队列中元素的最大个数
typedef struct{
ElemType data[MaxSize]; //用静态数组存放队列元素
int front,rear; //对头指针和队尾指针
}SqQueue;
//入队
bool EnQueue(SqQueue &Q,ElemType x){
if(队列已满)
return false;
Q.data[Q.rear] = x;
Q.rear = (Q.rear + 1) % MaxSize;//如果rear为9的时候 1+9=10 10/10 = 0 ==>rear会回到头结点
return true;
}
取模运算,即取余运算。两个整数a,b,a%b == a除以b的余数
{0,1,2,3,…,MaxSize-1}将存储空间在逻辑上变成了“环状”
模运算将无线限的整数域映射到有限的整数集合{0,1,2,3,…,b-1}上
4、循环队列(用模运算将存储空间在逻辑上变成了“环状”)
(1)入队操作
Q.data[Q.rear] = x; //新元素插入队尾
Q.rear = (Q.rear + 1) % MaxSize;//队尾指针加1取模
队列已满的条件:对尾指针的再下一个位置是队头,既(Q.rear+1)%MaxSize==Q.front
代价:牺牲一个存储单元
//判断队列是否为空
bool QueueEmpty(SqQueue Q){
if(Q.rear == Q.front) //判断队空(对空条件)
return;
else
return false;
}
//入队
bool EnQueue(SqQueue &Q,ElemType x){
if((Q.rear+1) % MaxSize == Q.front ) //判断队满
return false; //队满则报错
Q.data[Q.rear] = x; //新元素插入队尾
Q.rear=(Q.rear + 1)%MaxSize; //队尾指针加1取模(用模运算将存储空间在逻辑上变成了“环状”)
return true;
}
(2)出队操作(只能让队头元素出队)
//出队(删除一个队头元素,并用x返回)
bool DeQueue(SqQueue &Q,ElemType &x){
if(Q.rear == Q.front)//判断队空
return false;//队空则报错
x=Q.data[Q.front];
Q.front=(Q.front+1)%MaxSize;//队头指针后移
return true;
}
获得对头元素的值,用x返回
bool DeQueue(SqQueue &Q,ElemType &x){
if(Q.rear == Q.front)//判断队空
return false;//队空则报错
x=Q.data[Q.front];
return true;
}
(3)方案一:判断队列已满/已空
#define MaxSize 10
typedef struct{
ElemType data[MaxSize];
int front,rear;//初始化rear=front=0
}SqQueue;
队列元素个数
(rear+MaxSize-front)%MaxSize;
当前上述左边的情况下的时候
(2+10-3)%10 = 9 % 10 = 9
(4)方案二:判断队列已满/已空(不浪费那片存储空间)
#define MaxSize 10
typedef struct{
ElemType data[MaxSize];
int front,rear;//初始化rear=front=0
int size;//队列当前的长度(插入成功size++,删除成功size--) (初始化的时候rear=front=0 size=0)
}SqQueue;
插入元素
删除元素
(5)方案三:判断队列已满/已空(不浪费那片存储空间)
#define MaxSize 10
typedef struct{
ElemType data[MaxSize];
int front,rear;//初始化rear=front=0
int tag;//最近进行的是删除/插入
}SqQueue;
每次删除操作成功的时候,都令tag=0
每次插入操作成功的时候,都令tag=1
只有删除操作,才可能导致队空
只有插入操作,才可能导致队满
(6)其他出题方法
判断队列是否为空
(Q.rear+1)%MaxSize == Q.front
判断队列是否已满
方案一:牺牲一个存储单元
方案二:增加辅助变量
在这里插入图片描述
(7)知识回顾与重要考点
5、队列的链式的实现
(1)知识总览
(2)队列的链式
#include<stdio.h>
typedef struct LinkNode{ //链式队列结点
ElemType data;
struct LinkNode *next;
}LinkNode;
typedef struct { //链式队列
LinkNode *front,*rear; //队列的对头和队尾指针
}LinkQueue;
链队列–链式存储实现的队列
(3)初始化(带头结点)
#include<stdio.h>
typedef struct LinkNode{ //链式队列结点
ElemType data;
struct LinkNode *next;
}LinkNode;
typedef struct { //链式队列
LinkNode *front,*rear; //队列的对头和队尾指针
}LinkQueue;
//初始化队列(带头结点)
void InitQueue(LinkQueue &Q){
//初始化front rear 都指向头结点
Q.front = Q.rear = (LinkNode*)malloc(sizeof(LinkNode));//并分配内存空间
Q.front->next = NULL;//头结点的指针指向空
}
//判断队列是否为空
bool IsEmpty(LinkQueue &Q){
if(Q.front == Q.rear)
return true;
else
return false;
}
void testLinkQueue(){
LinkQueue Q;//声明一个队列
InitQueue(Q);//初始化
//...后续操作...
}
(4)初始化(不带头结点)
//初始化队列(不带头结点)
void InitQueue(LinkQueue &Q){
//初始时front ,rear都指向NULL
Q.front = NULL;
Q.rear = NULL;
}
//判断队列是否为空(不带头结点)
bool IsEmpty(LinkQueue Q){
if(Q.front == NULL)
return true;
else
return false;
}
rear–>NULL
front–>NULL
不带头结点的空队列
(5)入队(带头结点)
//入队(带头结点)
//新元素入队(带头结点)
void EnQueue(LinkQueue &Q,ElemType x){
LinkNode *s = (LinkNode *)malloc(sizeof(LinkNode));//对链表分配内存空间
s->data = x;
s->next = NULL;
Q.rear->next = s; //新结点插入到rear之后
Q.rear = s; //修改表尾指针
}
(6)入队(不带头结点)
//新元素入队(不带头结点)
void EnQueue(LinkQueue &Q,ElemType x){
LinkNode *s = (LinkNode *)malloc(sizeof(LinkNode));
s->data = x;
s->next = NULL;
if(Q.front == NULL){ //在空队列中插入第一个元素
Q.front = s; //修改对头队尾指针
Q.front = s; //不带头结点的队列,第一个元素入队时需要特别处理
Q.rear = s;
}else{
Q.rear->next = s;//新结点插入到rear结点之后
Q.rear=s; //修改rear指针
}
}
(7)出队(带头结点)
//队头元素出队(不带头结点)
bool DeQueue(LinkQueue &Q,ElemType &x){
if(Q.front == Q.rear)
return false;//队空
LinkNode *p = Q.front->next;
x=p->data;//用变量x返回队头元素
Q.front->next = p->next;//修改头结点的next指针
if(Q.rear == p) //此次是最后一个结点出队
Q.rear = Q.front; //修改rear指针
free(p); //释放结点空间
return true;
}
(8)出队(不带头结点)
//队头元素出队(不带头结点)
bool DeQueue(LinkQueue &Q,ElemType &x) {//传入参数是队列和要出队的元素的地址值
if(Q.front == NULL)//判断传入队列的首地址值是否为空,如果为空则直接返回false
return false; //空队
LinkNode *p = Q.front;//p指向此次出栈的头结点,声明队列类型的指针指向队列的头位置
x=p->data; //用变量x返回队头元素
Q.front = p->next; //修改front指针
if(Q.rear == p){ //修改front指针
Q.front = NULL; //front指向NULL
Q.rear = NULL;//rear 指向NULL
}
free(p); //释放结点空间
return true;
}
(9)队列满的条件
三、双端队列
1、双端队列是运行两端插入,两端删除的线性表
如果只使用其中一端的插入,删除操作,则效果等同于栈。
2、输入受限的双端队列:只允许从一端插入,两端删除的线性表
3、输出受限的双端队列:只允许从两端插入,一端删除的线性表
4、考点:判断输出序列合法性:若数据元素输入序列为1,2,3,4,则那些输出序列是合法的,那些是违法的?
(1)栈
以下红色为非法的输出序列
(2)输入受限的双端队列
(3)输出受限的双端队列
6、知识点回顾
以上是关于C/C++语言数据结构快速入门(代码解析+内容解析)队列的主要内容,如果未能解决你的问题,请参考以下文章
C/C++语言数据结构快速入门(代码解析+内容解析)栈的应用
C/C++语言数据结构快速入门(代码解析+内容解析)队列的应用