队列
队列的定义
队列简称队,它是一种运算受限的线性表,其仅允许在表的一端进行插入,而在表的另一端进行删除。把进行插入的一端称做队尾(rear),进行删除的一端称做队头(front)。
特点:先进先出
队列的顺序存储结构
普通顺序队列
先定义一下顺序队列的数据类型:
const int maxn = 10;
typedef struct{
int data[maxn];
int front,rear;//队首和队尾指针
}Queue;
//顺序队的四要素(初始时front=rear=-1):
//队空条件:front=rear
//队满条件:rear=MaxSize-1
//元素e进队:rear++;data[rear]=e;
//元素e出队:front++;e=data[front];
//rear指向队尾元素;front指向队头元素的前一个位置。
顺序队的基本操作:
-
初始化队列InitQueue(q)
//初始化一个队列 void InitQueue(Queue *&q){ q =(Queue *) malloc(sizeof(Queue)); q->front=q->rear = -1; }
-
销毁队列DestroyQueue(q)
//销毁队列 void DestroyQueue(Queue *&q){ free(q); }
-
判断队列是否为空IsEmpty(q)
bool IsEmpty(Queue *q){ return q->front==q->rear; }
-
进队列enQueue(q,e)
//入队 bool enQueue(Queue *&q,int e){ if (q->rear==maxn-1) return false; q->rear++; q->data[q->rear]=e; return true; }
-
出队列deQueue(q,e)
扫描二维码关注公众号,回复: 10180364 查看本文章//出队 bool deQueue(Queue *&q,int &e){ if(IsEmpty(q)) return false; q->front++; e=q->data[q->front]; return true; }
整合一下
#include<stdio.h>
#include<iostream>
#include<stdlib.h>
using namespace std;
const int maxn = 10;
typedef struct{
int data[maxn];
int front,rear;//队首和队尾指针
}Queue;
//初始化一个队列
void InitQueue(Queue *&q){
q =(Queue *) malloc(sizeof(Queue));
q->front=q->rear = -1;
}
//销毁队列
void DestroyQueue(Queue *&q){
free(q);
}
bool IsEmpty(Queue *q){
return q->front==q->rear;
}
//入队
bool enQueue(Queue *&q,int e){
if (q->rear==maxn-1)
return false;
q->rear++;
q->data[q->rear]=e;
return true;
}
//出队
bool deQueue(Queue *&q,int &e){
if(IsEmpty(q))
return false;
q->front++;
e=q->data[q->front];
return true;
}
int main(){
Queue *qu;
int e,a[]={1,2,3,4,5,6,7,8,6,5};
InitQueue(qu);
if(IsEmpty(qu))
for(int i = 0;i<10;i++){
enQueue(qu,a[i]);
}
for(int i = 0;i<=qu->rear;i++){
printf("%d ",qu->data[i]);
}
printf("\n");
deQueue(qu,e);
deQueue(qu,e);
deQueue(qu,e);
printf("出队元素为 %d\n",e);
printf("这时头指针为%d\n",qu->front);
for(int i = qu->front;i<=qu->rear;i++){
printf("%d ",qu->data[i]);
}
printf("\n");
int s=enQueue(qu,e);
printf("%d",s);//这里结果是0,但我们刚才弹出了一个,应该是没有满才对,
//所以这样有一个缺陷那就是队列假溢出
}
就像看到的那样,这里队列假满溢出,所以我们设计一个环形的顺序表来做队列
当然,这里顺序表是不可能真的首尾相连的,我们是逻辑上实现首尾相连
环形顺序队列
数据类型一样
const int maxn = 10;
typedef struct{
int data[maxn];
int front,rear;//队首和队尾指针
}Queue;
//队空条件:front=rear
//队满条件:(rear+1)%MaxSize=front
//进队e操作:rear=(rear+1)%MaxSize; 将e放在rear处
//出队操作:front=(front+1)%MaxSize; 取出front处元素e;
环形顺序队的实现基本操作:
-
初始化队列InitQueue(q)
//初始化一个队列 void InitQueue(Queue *&q){ q =(Queue *) malloc(sizeof(Queue)); q->front=q->rear = 0; }
-
销毁队列DestroyQueue(q)
-
判断队列是否为空IsEmpty(q)
-
进队列enQueue(q,e)
//入队 bool enQueue(Queue *&q,int e){ if ((q->rear+1)%maxn==q->front) return false; q->rear=(q->rear+1)%maxn; q->data[q->rear]=e; return true; }
-
出队列deQueue(q,e)
//出队 bool deQueue(Queue *&q,int &e){ if(IsEmpty(q)) return false; q->front=(q->front+1)%maxn; e=q->data[q->front]; return true; }
整合一下
#include<stdio.h>
#include<iostream>
#include<stdlib.h>
using namespace std;
const int maxn = 10;
typedef struct{
int data[maxn];
int front,rear;//队首和队尾指针
}Queue;
//初始化一个队列
void InitQueue(Queue *&q){
q =(Queue *) malloc(sizeof(Queue));
q->front=q->rear =0;
}
//销毁队列
void DestroyQueue(Queue *&q){
free(q);
}
bool IsEmpty(Queue *q){
return q->front==q->rear;
}
//入队
bool enQueue(Queue *&q,int e){
if ((q->rear+1)%maxn==q->front)
return false;
q->rear=(q->rear+1)%maxn;
q->data[q->rear]=e;
return true;
}
//出队
bool deQueue(Queue *&q,int &e){
if(IsEmpty(q))
return false;
q->front=(q->front+1)%maxn;
e=q->data[q->front];
return true;
}
int main(){
Queue *qu;
int e,a[]={1,2,3,4,5,6,7,8,9,10};
InitQueue(qu);
if(IsEmpty(qu))
for(int i = 0;i<4;i++){
enQueue(qu,a[i]);
}
for(int i = qu->front;i<=qu->rear;i++){
printf("%d ",qu->data[i]);
}
printf("\n");
deQueue(qu,e);
deQueue(qu,e);
deQueue(qu,e);
printf("出队元素为 %d\n",e);
printf("这时头指针为%d\n",qu->front);
for(int i = qu->front;i<=qu->rear;i++){
printf("%d ",qu->data[i]);
}
printf("\n");
int s=enQueue(qu,e);
printf("是否成功入队 %d",s);
printf("\n");
for(int i = qu->front;i<=qu->rear;i++){
printf("%d ",qu->data[i]);
}
printf("\n");
}
这个环形队列只能存放maxn-1 个元素,因为要区分队满和队空的条件,下面我们用另外一种方法设计循环队列,
环形队列2
对于环形队列来说,如果知道队头指针和队列中 元素个数,则可以计算出队尾指针。
已知front、rear,求队中元素个数:
count=(rear-front+MaxSize)%MaxSize
已知front、count,求rear:
rear=(front+count)%MaxSize
已知rear、count,求front:
front=(rear-count+MaxSize)%MaxSize
这是定义环形队列的数据结构
const int maxn = 10;
typedef struct{
int data[maxn];
int front,count;//队首和元素个数
}Queue;
//队空条件:count=0
//队满条件:count=maxn
//进队e操作:rear=(rear+1)%MaxSize; 将e放在rear处
//出队操作:front=(front+1)%MaxSize; 取出front处元素e;
环形顺序队的实现基本操作:
-
初始化队列InitQueue(q)
//初始化一个队列 void InitQueue(Queue *&q){ q =(Queue *) malloc(sizeof(Queue)); q->front=q->count = 0; }
-
销毁队列DestroyQueue(q)
-
判断队列是否为空IsEmpty(q)
bool IsEmpty(Queue *q){ return q->count==0; }
-
进队列enQueue(q,e)
//入队 bool enQueue(Queue *&q,int e){ int rear;// 临时队尾 if(q->count==maxn) return false;//溢出 else{ rear = (count+front)%maxn; rear = (rear+1)%maxn;//队尾加一 q->data[rear]=e; q->count++;//元素个数加一 return true; } }
-
出队列deQueue(q,e)
//出队 bool deQueue(Queue *&q,int &e){ if(IsEmpty(q)) return false; else{ q->front=(q->front+1)%maxn; e=q->data[q->front]; q->count--; return true; } }
具体整合这里就不操作了,和上面类似
链队列
有头节点的链队
链队列,我们不但要有存放数据节点的单链表,还要有指向头节点和尾节点的单链表指针,
先来定义一下数据类型
typedef struct qnode{
int data;
struct qnode *next;
}Qnode;//这个其实就是个单链表
typedef struct{
Qnode *front;//指向单链表队头节点
Qnode *rear;//指向单链表队尾节点
}LQueue;//链队头节点
//队空条件:front=rear=NULL
//队满条件:不考虑
//进队e操作:将包含e的节点插入到单链表表尾
//出队操作:删除单链表首数据节点
链队列实现简单操作
-
初始化链队
void InitQueue(LQueue *&q){ q = (LQueue*)malloc(sizeof(LQueue)); q->front=q->rear=NULL; }
-
销毁一个链队
void DestroyQueue(LQueue *&q){
//我们需要销毁每个数据节点和链队头节点
Qnode *p = q->front,*r;
if(p!=NULL){
r = p->next;
while (r!=NULL){
free(p);
p=r;
r=p->next;
}//销毁数据节点
}
free(p);free(q);//销毁链队头节点
}
-
判断链队是否为空
bool IsEmpty(LQueue *q){ return q->rear ==NULL; }
-
进队
void enQueue(LQueue *&q,int e){ Qnode *p; p=(Qnode*)malloc(sizeof(Qnode)); p->data=e; p->next =NULL;//先创建一个数据节点; //考虑原来队列空和非空两种情况 if(IsEmpty(q)){ q->front = q->rear=p; } else{ q->rear->next=p; q->rear=p; } }
-
出队
bool deQueue(LQueue*&q,int &e){ Qnode *t; //先判断一下队列是否是空的 if(IsEmpty(q)) return false; t=q->front; if(q->front==q->rear)//原来队列只有一个节点 { q->front=q->rear=NULL; } else{ q->front=q->front->next; } e=t->data; free(t); return true; }
完整代码
#include<stdio.h>
#include<stdlib.h>
typedef struct qnode{
int data;
struct qnode *next;
}Qnode;//这个其实就是个单链表
typedef struct{
Qnode *front;//指向单链表队头节点
Qnode *rear;//指向单链表队尾节点
}LQueue;//链队头节点
void InitQueue(LQueue *&q){
q = (LQueue*)malloc(sizeof(LQueue));
q->front=q->rear=NULL;
}
void DestroyQueue(LQueue *&q){
//我们需要销毁每个数据节点和链队头节点
Qnode *p = q->front,*r;
if(p!=NULL){
r = p->next;
while (r!=NULL){
free(p);
p=r;
r=p->next;
}
}
free(p);free(q);
}
bool IsEmpty(LQueue *q){
return q->rear ==NULL;
}
void enQueue(LQueue *&q,int e){
Qnode *p;
p=(Qnode*)malloc(sizeof(Qnode));
p->data=e;
p->next =NULL;//先创建一个数据节点;
//考虑原来队列空和非空两种情况
if(IsEmpty(q)){
q->front = q->rear=p;
}
else{
q->rear->next=p;
q->rear=p;
}
}
bool deQueue(LQueue*&q,int &e){
Qnode *t;
//先判断一下队列是否是空的
if(IsEmpty(q))
return false;
t=q->front;
if(q->front==q->rear)//原来队列只有一个节点
{
q->front=q->rear=NULL;
}
else{
q->front=q->front->next;
}
e=t->data;
free(t);
return true;
}
int main(){
LQueue *q;
InitQueue(q);
int a[]={4,3,5,6,7},e;
for(int i=0;i<5;i++){
enQueue(q,a[i]);
}
for(int i=0;i<3;i++){
deQueue(q,e);
printf("%d ",e);
}
printf("%d ",q->front->data);
}
没有头节点的链队
没有头节点,只有指向队尾的指针作为唯一标识
先来定义一下数据类型
typedef struct qnode{
int data;
struct qnode *next;
}Qnode;//这个其实就是个单链表
typedef struct{
Qnode *front;//指向单链表队头节点
Qnode *rear;//指向单链表队尾节点
}LQueue;//链队头节点
//队空条件:rear=NULL
//队满条件:不考虑
//进队e操作:将包含e的节点插入到单链表表尾
//出队操作:删除单链表首数据节点
链队列实现简单操作
-
初始化链队
void InitLinkList(LinkList *&rear){ rear=NULL; }
-
销毁一个链队 这个没有什么特别的,和上面类似
-
判断链队是否为空
bool IsEmpty(LinkList *rear){ return rear==NULL; }
-
进队
void enQueue(LinkList *&rear,int e){ LinkList *q; q=(LinkList*)malloc(sizeof(LinkList)); //判断是否为空 q->data=e; if(IsEmpty(rear)){ q->next=q;//自己指自己 rear=q; } else{ q->next=rear->next;//这里,rear的next永远指着首节点 rear->next=q; rear=q; } }
-
出队
bool deQueue(LinkList *&rear,int &e){ LinkList *q; if(IsEmpty(rear)) return false;//队空 if(rear->next==rear){//只有一个节点 e=rear->data; free(rear);rear=NULL; } else { q=rear->next; e=q->data; rear->next=q->next; free(q); } return true ; }
完整代码
#include<stdlib.h>
#include<stdio.h>
typedef struct qnode{
int data;
qnode *next;
}LinkList;
void InitLinkList(LinkList *&rear){
rear=NULL;
}
bool IsEmpty(LinkList *rear){
return rear==NULL;
}
void enQueue(LinkList *&rear,int e){
LinkList *q;
q=(LinkList*)malloc(sizeof(LinkList));
//判断是否为空
q->data=e;
if(IsEmpty(rear)){
q->next=q;//自己指自己
rear=q;
}
else{
q->next=rear->next;//这里,rear的next永远指着首节点
rear->next=q;
rear=q;
}
}
bool deQueue(LinkList *&rear,int &e){
LinkList *q;
if(IsEmpty(rear))
return false;//队空
if(rear->next==rear){//只有一个节点
e=rear->data;
free(rear);rear=NULL;
}
else {
q=rear->next;
e=q->data;
rear->next=q->next;
free(q);
}
return true ;
}
int main(){
LinkList *rear;
int a[]{3,5,8,6,4},e;
InitLinkList(rear);
for(int i=0;i<5;i++){
enQueue(rear,a[i]);
}
for(int i=0;i<3;i++){
deQueue(rear,e);
printf("%d ",e);
}
}
我来要赞啦啊,如果觉得可以学到些什么的话就点个赞再走吧
欢迎各位路过的大佬评论指正