目录
循环队列
方式1:队头队尾为0(浪费一个空间)
//
// @Author: Brisa
// @Date: 2021/8/27
// @Description: 循环队列(顺序存储) 队头队尾:0
//
#include<stdio.h>
#define MaxSize 10 //定义队列中元素的最大个数
#define ElemType int
//顺序队列类型定义
typedef struct {
ElemType data[MaxSize]; //静态数组存放队列元素
int front, rear; //队头指针、队尾指针
}SqQueue;
/*函数声明*/
void InitQueue(SqQueue &Q); //1.初始化队列
bool QueueEmpty(SqQueue Q); //2.判空
bool EnQueue(SqQueue &Q, ElemType e); //3.入队
bool ExQueue(SqQueue &Q, ElemType &e); //4.出队
bool GetHead(SqQueue Q, ElemType &e); //5.获取队头元素
/*具体函数*/
//1.初始化队列
void InitQueue(SqQueue &Q){
/*初始时,队头队尾指针都指向0*/
Q.front = 0; //队头指针指向队头元素
Q.rear = 0; //队尾指针指向队尾元素的最后一个位置,即【下一个要插入的位置】
}
//2.判空
bool QueueEmpty(SqQueue Q){
return (Q.front==Q.rear);
}
//3.入队
bool EnQueue(SqQueue &Q, ElemType e){
if((Q.rear+1) % MaxSize == Q.front) //【队满】,报错
return false;
Q.data[Q.rear] = e; //新元素插入队尾
Q.rear = (Q.rear + 1) % MaxSize; //队尾指针+1取模
// 用模运算将存储空间在逻辑上变成“环状”,这也是叫循环队列的原因
return true;
}
//4.出队
bool ExQueue(SqQueue &Q, ElemType &e){
if(Q.front == Q.rear) //【队空】,报错
return false;
e = Q.data[Q.front]; //返回队头元素的值
Q.front = (Q.front + 1) % MaxSize; //队头指针+1取模,指向下一个元素
return true;
}
//5.获取队头元素
bool GetHead(SqQueue Q, ElemType &e){
if(Q.front == Q.rear) //【队空】,报错
return false;
e = Q.data[Q.front]; //返回队头元素的值
return true;
}
int main(){
//声明一个循环队列
SqQueue Q;
//初始化循环队列
InitQueue(Q);
//判空
printf("当前循环队列是否为空:%s \n", QueueEmpty(Q)?"是":"否");
//入队
ElemType e1;
printf("请输入你想要入队的值:");
scanf("%d", &e1);
if(EnQueue(Q,e1))
printf("新元素入队成功!\n");
else
printf("队列已满,新元素入队失败!\n");
//读取队头元素
ElemType e2;
if(GetHead(Q,e2))
printf("队头元素读取成功,当前队头元素为:%d\n", e2);
else
printf("队列为空,队头元素读取成功失败!\n");
//出队
ElemType e3;
if(ExQueue(Q,e3))
printf("队头元素出队成功,出队元素值为:%d\n", e3);
else
printf("队列为空,队头元素出队失败!\n");
//读取队头元素
ElemType e4;
if(GetHead(Q,e4))
printf("队头元素读取成功,当前队头元素为:%d\n", e4);
else
printf("队列为空,队头元素读取成功失败!\n");
return 0;
}
方式2:新增一个size变量,表示当前队列长度(不浪费空间)
//
// @Author: Brisa
// @Date: 2021/8/27
// @Description: 循环队列(顺序存储) 队头队尾:0
// 新增一个size变量,表示当前队列长度
// 为判空判满提供方便且节省一个队列单元
//
#include<stdio.h>
#define MaxSize 10 //定义队列中元素的最大个数
#define ElemType int
//顺序队列类型定义
typedef struct {
ElemType data[MaxSize]; //静态数组存放队列元素
int front, rear; //队头指针、队尾指针
int size; //【引入辅助变量size表示队列当前长度,为判空判满提供方便且节省一个队列单元】
}SqQueue;
/*函数声明*/
void InitQueue(SqQueue &Q); //1.初始化队列
bool QueueEmpty(SqQueue Q); //2.判空
bool EnQueue(SqQueue &Q, ElemType e); //3.入队
bool ExQueue(SqQueue &Q, ElemType &e); //4.出队
bool GetHead(SqQueue Q, ElemType &e); //5.获取队头元素
/*具体函数*/
//1.初始化队列
void InitQueue(SqQueue &Q){
/*初始时,队头队尾指针都指向0*/
Q.front = 0; //队头指针指向队头元素
Q.rear = 0; //队尾指针指向队尾元素的最后一个位置,即【下一个要插入的位置】
Q.size = 0; //队列初始化长度为0
}
//2.判空
bool QueueEmpty(SqQueue Q){
return (Q.size == 0); //队列中元素个数为0则为空
}
//3.入队
bool EnQueue(SqQueue &Q, ElemType e){
if(Q.size == MaxSize) //【队满】,报错
return false;
Q.data[Q.rear] = e; //新元素插入队尾
Q.rear = (Q.rear + 1) % MaxSize; //队尾指针+1取模
// 用模运算将存储空间在逻辑上变成“环状”,这也是叫循环队列的原因
Q.size++; //队列长度+1
return true;
}
//4.出队
bool ExQueue(SqQueue &Q, ElemType &e){
if(Q.size == 0) //【队空】,报错
return false;
e = Q.data[Q.front]; //返回队头元素的值
Q.front = (Q.front + 1) % MaxSize; //队头指针+1取模,指向下一个元素
Q.size--; //队列长度-1
return true;
}
//5.获取队头元素
bool GetHead(SqQueue Q, ElemType &e){
if(Q.size == 0) //【队空】,报错
return false;
e = Q.data[Q.front]; //返回队头元素的值
return true;
}
int main(){
//声明一个循环队列
SqQueue Q;
//初始化循环队列
InitQueue(Q);
//判空
printf("当前循环队列是否为空:%s \n", QueueEmpty(Q)?"是":"否");
//入队
ElemType e1;
printf("请输入你想要入队的值:");
scanf("%d", &e1);
if(EnQueue(Q,e1))
printf("新元素入队成功!\n");
else
printf("队列已满,新元素入队失败!\n");
//读取队头元素
ElemType e2;
if(GetHead(Q,e2))
printf("队头元素读取成功,当前队头元素为:%d\n", e2);
else
printf("队列为空,队头元素读取成功失败!\n");
//出队
ElemType e3;
if(ExQueue(Q,e3))
printf("队头元素出队成功,出队元素值为:%d\n", e3);
else
printf("队列为空,队头元素出队失败!\n");
//读取队头元素
ElemType e4;
if(GetHead(Q,e4))
printf("队头元素读取成功,当前队头元素为:%d\n", e4);
else
printf("队列为空,队头元素读取成功失败!\n");
return 0;
}
方式3:新增tag变量表示最后一次操作是入队还是出队 0:出队 1:入队(不浪费空间)
//
// @Author: Brisa
// @Date: 2021/8/27
// @Description: 循环队列(顺序存储) 队头队尾:0
// 新增tag变量表示最后一次操作是入队还是出队 0:出队 1:入队
// 为判空判满提供方便且节省一个队列单元
//
#include<stdio.h>
#define MaxSize 10 //定义队列中元素的最大个数
#define ElemType int
//顺序队列类型定义
typedef struct {
ElemType data[MaxSize]; //静态数组存放队列元素
int front, rear; //队头指针、队尾指针
int tag; //【引入辅助变量tag表示最后一次入队出队,为判空判满提供方便且节省一个队列单元】
}SqQueue;
/*函数声明*/
void InitQueue(SqQueue &Q); //1.初始化队列
bool QueueEmpty(SqQueue Q); //2.判空
bool EnQueue(SqQueue &Q, ElemType e); //3.入队
bool ExQueue(SqQueue &Q, ElemType &e); //4.出队
bool GetHead(SqQueue Q, ElemType &e); //5.获取队头元素
/*具体函数*/
//1.初始化队列
void InitQueue(SqQueue &Q){
/*初始时,队头队尾指针都指向0*/
Q.front = 0; //队头指针指向队头元素
Q.rear = 0; //初始化时【队尾指针指向队头指针的前一个元素】,这样在之后的操作中队尾指针始终指向队尾元素
Q.tag = 0; //初始化最后一次操作为删除,因为当前队空
}
//2.判空
bool QueueEmpty(SqQueue Q){
return (Q.front==Q.rear && Q.tag==0);
//队尾+1=队头 且 最后一次进行是出队操作则队空
}
//3.入队
bool EnQueue(SqQueue &Q, ElemType e){
//队尾=队头 且 最后一次进行是入队操作则队满
if(Q.rear==Q.front && Q.tag == 1) //【队满】,报错
return false;
// 用模运算将存储空间在逻辑上变成“环状”,这也是叫循环队列的原因
Q.data[Q.rear] = e; //新元素插入队尾
Q.rear = (Q.rear + 1) % MaxSize; //队尾指针+1取模
Q.tag = 1; //标识此次进行的是入队操作
return true;
}
//4.出队
bool ExQueue(SqQueue &Q, ElemType &e){
if(Q.rear==Q.front && Q.tag == 0) //【队空】,报错
return false;
e = Q.data[Q.front]; //返回队头元素的值
Q.front = (Q.front + 1) % MaxSize; //队头指针+1取模,指向下一个元素
Q.tag = 0; //标识此次进行的是出队操作
return true;
}
//5.获取队头元素
bool GetHead(SqQueue Q, ElemType &e){
if(Q.rear==Q.front && Q.tag == 0) //【队空】,报错
return false;
e = Q.data[Q.front]; //返回队头元素的值
return true;
}
int main(){
//声明一个循环队列
SqQueue Q;
//初始化循环队列
InitQueue(Q);
//判空
printf("当前循环队列是否为空:%s \n", QueueEmpty(Q)?"是":"否");
//入队
ElemType e1;
printf("请输入你想要入队的值:");
scanf("%d", &e1);
if(EnQueue(Q,e1))
printf("新元素入队成功!\n");
else
printf("队列已满,新元素入队失败!\n");
//本段代码仅用作测试-循环入队直至队满
/*ElemType e1;
printf("初始rear为:%d\n", Q.rear);
int n=1;
while (!(Q.rear== Q.front && Q.tag == 1)) { //队不满则一直入队
printf("请输入第%d个元素的值:",n);
scanf("%d", &e1);
EnQueue(Q, e1);
printf("当前rear为:%d\n", Q.rear); //查看入队后的rear变化
n++;
}*/
//读取队头元素
ElemType e2;
if(GetHead(Q,e2))
printf("队头元素读取成功,当前队头元素为:%d\n", e2);
else
printf("队列为空,队头元素读取成功失败!\n");
//出队
ElemType e3;
if(ExQueue(Q,e3))
printf("队头元素出队成功,出队元素值为:%d\n", e3);
else
printf("队列为空,队头元素出队失败!\n");
/*本段代码仅用作测试-循环入队直至队满*/
/*ElemType e3;
printf("初始front为:%d\n", Q.rear);
n=1;
while (!(Q.rear== Q.front && Q.tag == 0)) { //队不空则一直出队
ExQueue(Q, e3);
printf("出队元素值为:%d,当前front为:%d,\n", e3, Q.front); //查看入队后的rear变化
n++;
}*/
//读取队头元素
ElemType e4;
if(GetHead(Q,e4))
printf("队头元素读取成功,当前队头元素为:%d\n", e4);
else
printf("队列为空,队头元素读取成功失败!\n");
return 0;
}
链队列
1.带头结点
//
// @Author: Brisa
// @Date: 2021/8/28
// @Description: 链式队列(带头结点)
//
#include<stdio.h>
#include <stdlib.h>
#define ElemType int
//链式队列结点
typedef struct LinkNode{
ElemType data; //数据域
struct LinkNode *next; //指针域
}LinkNode;
//链式队列
typedef struct {
LinkNode *front, *rear; //队列的队头和队尾指针
}LinkQueue;
/*函数声明*/
void InitQueue(LinkQueue &Q); //1.初始化队列(带头结点)
bool EmptyQueue(LinkQueue Q); //2.判空
bool EnQueue(LinkQueue &Q, ElemType e); //3.入队
bool ExQueue(LinkQueue &Q, ElemType &e); //4.出队
bool GetTop(LinkQueue Q, ElemType &e); //5.获取队头元素
/*具体函数*/
//1.初始化队列(带头结点)
void InitQueue(LinkQueue &Q){
//初始化时,front和rear都指向头结点
Q.front = Q.rear = (LinkNode *)malloc(sizeof(LinkNode));
Q.front->next = NULL; //头结点初始化为NULL
}
//2.判空
bool EmptyQueue(LinkQueue Q){
return (Q.front == Q.rear);
// 或者 Q.front->next==NULL;
}
//3.入队
bool EnQueue(LinkQueue &Q, ElemType e){
LinkNode *p = (LinkNode *)malloc(sizeof(LinkNode));
if(p == NULL)
return false;//内存不足,分配失败
p->data = e;
p->next = NULL;
Q.rear->next = p; //新结点插入到rear
Q.rear = p; //修改表尾指针
return true;
}
//4.出队
bool ExQueue(LinkQueue &Q, ElemType &e){
if(Q.front == Q.rear) //队空
return false;
LinkNode *q = Q.front->next; //q结点指向front之后的结点
e = q->data; //用e返回队头元素的值
Q.front->next = q->next; //更改头结点的next
if(Q.rear == q) //【若是最后一个结点出队,则rear要修改】
Q.rear = Q.front;
free(q);
return true;
}
//5.获取队头元素
bool GetTop(LinkQueue Q, ElemType &e){
if(Q.front == Q.rear) //队空
return false;
LinkNode *q = Q.front->next; //q结点指向front之后的结点
e = q->data; //用e返回队头元素的值
return true;
}
int main(){
//声明一个链式队列
LinkQueue Q;
//1.初始化队列(带头结点)
InitQueue(Q);
//2.判空
printf("当前链式队列(带头结点)是否为空:%s \n", EmptyQueue(Q)?"是":"否");
//3.入队
ElemType e1;
printf("请输入你想要入队的值:");
scanf("%d", &e1);
if(EnQueue(Q, e1)){
printf("新元素入队成功!\n");
}else{
printf("内存不足,分配失败!\n");
}
//4.获取队头元素
ElemType e2;
if(GetTop(Q, e2)){
printf("获取队头元素成功,队头元素为:%d\n", e2);
} else{
printf("队列为空,获取队头元素失败!\n");
}
//5.出队
ElemType e3;
if(ExQueue(Q, e3)){
printf("出队成功,出队队头元素为:%d\n", e3);
} else{
printf("队列为空,出队失败!\n");
}
//6.获取队头元素
ElemType e4;
if(GetTop(Q, e4)){
printf("获取队头元素成功,队头元素为:%d\n", e4);
} else{
printf("队列为空,获取队头元素失败!\n");
}
return 0;
}
2.不带头结点
//
// @Author: Brisa
// @Date: 2021/8/28
// @Description: 链式队列(不带头结点)
//
#include<stdio.h>
#include<stdlib.h>
#define ElemType int
//链式队列结点
typedef struct LinkNode{
ElemType data; //数据域
struct LinkNode *next; //指针域
}LinkNode;
//链式队列
typedef struct {
LinkNode *front, *rear; //队列的队头和队尾指针
}LinkQueue;
/*函数声明*/
void InitQueue(LinkQueue &Q); //1.初始化队列(带头结点)
bool EmptyQueue(LinkQueue Q); //2.判空
bool EnQueue(LinkQueue &Q, ElemType e); //3.入队
bool ExQueue(LinkQueue &Q, ElemType &e); //4.出队
bool GetTop(LinkQueue Q, ElemType &e); //5.获取队头元素
/*具体函数*/
//1.初始化队列(带头结点)
void InitQueue(LinkQueue &Q){
//初始化时,front和rear都指向NULL
Q.front = NULL;
Q.rear = NULL; //头结点初始化为NULL
}
//2.判空
bool EmptyQueue(LinkQueue Q){
return (Q.front == NULL);
}
//3.入队
bool EnQueue(LinkQueue &Q, ElemType e){
LinkNode *p = (LinkNode *)malloc(sizeof(LinkNode));
if(p == NULL)
return false;//内存不足,分配失败
p->data = e;
p->next = NULL;
if(Q.front ==NULL){ //在空队列中插入第一个元素,【不带头结点的队列,第一个元素入队要特别处理】
//修改队头队尾指针
Q.front = p;
Q.rear = p;
} else{
Q.rear->next = p; //新结点插入到rear
Q.rear = p; //修改表尾指针
}
return true;
}
//4.出队
bool ExQueue(LinkQueue &Q, ElemType &e){
if(Q.front == NULL) //队空
return false;
LinkNode *q = Q.front; //q结点指向front的结点
e = q->data; //用e返回队头元素的值
Q.front = q->next; //更改头结点的next
if(Q.rear == q) { //【若是最后一个结点出队,则front,rear要修改为NULL】
Q.rear = NULL;
Q.front = NULL;
}
free(q);
return true;
}
//5.获取队头元素
bool GetTop(LinkQueue Q, ElemType &e){
if(Q.front == NULL) //队空
return false;
LinkNode *q = Q.front; //q结点指向front之后的结点
e = q->data; //用e返回队头元素的值
return true;
}
int main(){
//声明一个链式队列
LinkQueue Q;
//1.初始化队列(不带头结点)
InitQueue(Q);
//2.判空
printf("当前链式队列(不带头结点)是否为空:%s \n", EmptyQueue(Q)?"是":"否");
//3.入队
ElemType e1;
printf("请输入你想要入队的值:");
scanf("%d", &e1);
if(EnQueue(Q, e1)){
printf("新元素入队成功!\n");
}else{
printf("内存不足,分配失败!\n");
}
//4.获取队头元素
ElemType e2;
if(GetTop(Q, e2)){
printf("获取队头元素成功,队头元素为:%d\n", e2);
} else{
printf("队列为空,获取队头元素失败!\n");
}
//5.出队
ElemType e3;
if(ExQueue(Q, e3)){
printf("出队成功,出队队头元素为:%d\n", e3);
} else{
printf("队列为空,出队失败!\n");
}
//6.获取队头元素
ElemType e4;
if(GetTop(Q, e4)){
printf("获取队头元素成功,队头元素为:%d\n", e4);
} else{
printf("队列为空,获取队头元素失败!\n");
}
return 0;
}
参考来源:
数据结构代码参考博客
《王道数据结构》