顺序循环队列与链队列

发布于:2022-12-07 ⋅ 阅读:(574) ⋅ 点赞:(0)

今天学习了队列,一种是顺序循环队列,一种是链队列,我个人认为链队列相对好用一点,毕竟链队列不用考虑“假溢出”的问题,下面是我整理的关于队列的一些基本操作

目录

一、顺序循环队列 

1.1 初始化一个顺序循环队列

1.2 判断队列是否为空

1.3 入队

1.4 出队

1.5 打印队列

1.6 代码实现

1.6.1 完整代码

1.6.2 运行结果

二、链队列

2.1 初始化一个链队列

2.2 判断队列是否为空

2.3 入队

2.4 出队

2.5 打印队列

2.6 代码实现

2.6.1 完整代码

2.6.2 运行结果

三、总结


 

我们先来看个问题

 【问题描述】

实现循环队列的基本操作。(循环队列最大长度不超过20)

【输入形式】

输入若干个整数(以空格分隔),其中0表示做出队操作,不为0的整数为入队元素。

【输出形式】

依次输出队列的全部元素,若队列为空,则输出“empty”

【样例输入1】

1 2 3 4 5 6
【样例输出1】

1 2 3 4 5 6

【样例输入2】

1 2 3 0 0 4 0 5
【样例输出2】

4 5

【样例输入3】

1 0 2 0 3 0
【样例输出3】

empty

【样例输入4】

1 0 2 0 0 3 0 0 0
【样例输出4】

empty

下面我们将分别通过顺序循环队列和链队列来实现以上操作

一、顺序循环队列 

  顺序循环队列需要两个指针,一个用来入队,一个用来出队

  顺序循环队列是个在数组中移动的队列

  顺序循环队列主要要考虑“假溢出”的问题,为了防止“假溢出”,我们通过(front+1)%MAX来实现

1.1 初始化一个顺序循环队列

#include<stdio.h>
#include<malloc.h>
#define MAX 10
typedef struct Queue{
	int *base;       //可以理解为一个数组
	int front;       //指向队头的指针   可以理解为数组的下标
	int rear;        //指向队尾的指针   可以理解为数组的下标
	int len;         //队列的长度,方便打印队列
}Queue,*PQueue;
int Init_Queue(PQueue Q){
	Q->base=(int *)malloc(MAX*sizeof(int));   //初始化分配一个空间
	Q->front=Q->rear=0;                //初始化队头队尾在一起
	Q->len=0;                          //初始化队列长度为0
	return 1;
}

1.2 判断队列是否为空

int Empty_Queue(PQueue Q){
	if(Q->front==Q->rear)     //当队头和队尾指针在一起的时候,说明是个空队
	return 1;
	else
	return 0;
}

1.3 入队

  入队前一定要先判断队列是否已经满了,满了就不能再入队了

int Push_Queue(PQueue Q,int e){
	if((Q->rear+1)%MAX==Q->front) return 0;    //首先要判断队列是否满了
	Q->base[Q->rear]=e;           //满了无法入队,没满可以入队
	Q->rear=(Q->rear+1)%MAX;      //这个方法可以让队列成为循环队列
	Q->len++;                     //每次入队队列长度增加1
	return 1;
}

1.4 出队

  出队前一定要判断队列是否已经空了,如果队列空了,那么就没办法出队了

int Pop_Queue(PQueue Q,int *e){
	if(Q->front==Q->rear) return 0;   //出队前要先判断是否队空
	*e=Q->base[Q->front];             //队列不空可以出队
	Q->front=(Q->front+1)%MAX;        //这个方法可以循环出队
	Q->len--;                         //出队后队长减1
	return 1;
}

1.5 打印队列

int Print_Queue(PQueue Q){
	int i;
	for(i=0;i<Q->len;i++){
		printf("%d ",Q->base[Q->front+i]);    //将队列打印出来
	}
	printf("\n");
	return 1;
}

1.6 代码实现

1.6.1 完整代码

#include<stdio.h>
#include<malloc.h>
#define MAX 10
typedef struct Queue{
	int *base;
	int front;
	int rear;
	int len;
}Queue,*PQueue;
int Init_Queue(PQueue Q){
	Q->base=(int *)malloc(MAX*sizeof(int));
	Q->front=Q->rear=0;
	Q->len=0;
	return 1;
}
int Empty_Queue(PQueue Q){
	if(Q->front==Q->rear)
	return 1;
	else
	return 0;
}
int Push_Queue(PQueue Q,int e){
	if((Q->rear+1)%MAX==Q->front) return 0;
	Q->base[Q->rear]=e;
	Q->rear=(Q->rear+1)%MAX;
	Q->len++;
	return 1;
}
int Pop_Queue(PQueue Q,int *e){
	if(Q->front==Q->rear) return 0;
	*e=Q->base[Q->front];
	Q->front=(Q->front+1)%MAX;
	Q->len--;
	return 1;
}
int Get_Queue(PQueue Q,int *e){
	if(Q->front==Q->rear) return 0;
	*e=Q->base[Q->front];
	return 1;
}
int Print_Queue(PQueue Q){
	int i;
	for(i=0;i<Q->len;i++){
		printf("%d ",Q->base[Q->front+i]);
	}
	printf("\n");
	return 1;
}
int main(){
	Queue Q;
	int e;
	Init_Queue(&Q);
	while(scanf("%d",&e)==1){
		if(e==0){
			Pop_Queue(&Q,&e);
		}else{
			Push_Queue(&Q,e);
		}
	}
	if(Empty_Queue(&Q)==1){
		printf("empty\n");
	}else{
		Print_Queue(&Q);
	}
	return 0;
}

1.6.2 运行结果

05a72125ed59436e997e35f6135ce617.png

4ec0932d661344b8a4ca470467184ae2.png

f8cb83e572104f57bd0d7d72d4bf2758.png 

abc80e8b5a254e2d8b32a119ac957e5f.png 

二、链队列(带头结点单链表)

  我们用的是带头结点的单链表,方便出队

  链队列需要两个指针,分别用来入队和出队

  链队列不用考虑“假溢出”问题,操作起来更加方便

2.1 初始化一个链队列

#include<stdio.h>
#include<malloc.h>
typedef struct Node{       //每个结点
	int data;
	struct Node *next;
}Node,*PNode; 
typedef struct Queue{      //保存两个指针
	PNode front,rear;
}Queue,*PQueue;
int Init_Queue(PQueue Q){
	PNode P=(PNode)malloc(sizeof(Node));
	P->next=NULL;
	Q->front=Q->rear=P;    //初始队尾指针在队头指针位置
	return 1;
}

2.2 判断队列是否为空

int Empty_Queue(PQueue Q){
	if(Q->front==Q->rear)    //当队尾指针在队头指针处时,队列为空
	return 1;
	else
	return 0;
}

2.3 入队

  链队列入队不用考虑“假溢出”问题,操作起来方便

int Push_Queue(PQueue Q,int e){
	PNode Pnew=(PNode)malloc(sizeof(Node)); //新建一个结点,用于入队
	Pnew->next=NULL;     
	Pnew->data=e;   
	Q->rear->next=Pnew;      //入队操作只用尾指针rear
	Q->rear=Pnew;
	return 1;
}

2.4 出队

int Pop_Queue(PQueue Q,int *e){
	if(Q->front==Q->rear) return 0;     //出队先判断是否队空
	*e=Q->front->next->data;
	if(Q->front->next==Q->rear){        //当只剩一个有效结点的时候,为了避免尾指针丢失
		Q->front->next=NULL;
        Q->rear=Q->front;               //我们删除结点后要让尾指针指向头结点
	}else{
		Q->front->next=Q->front->next->next;   
	}
	return 1;
}

2.5 打印队列

int Print_Queue(PQueue Q){
	PNode P=Q->front->next;
	while(P){
		printf("%d ",P->data);    //和打印单链表类似
		P=P->next;
	}
	printf("\n");
}

2.6 代码实现

2.6.1 完整代码

#include<stdio.h>
#include<malloc.h>
typedef struct Node{
	int data;
	struct Node *next;
}Node,*PNode;
typedef struct Queue{
	PNode front,rear;
}Queue,*PQueue;
int Init_Queue(PQueue Q){
	PNode P=(PNode)malloc(sizeof(Node));
	P->next=NULL;
	Q->front=Q->rear=P;
	return 1;
}
int Empty_Queue(PQueue Q){
	if(Q->front==Q->rear)
	return 1;
	else
	return 0;
}
int Push_Queue(PQueue Q,int e){
	PNode Pnew=(PNode)malloc(sizeof(Node));
	Pnew->next=NULL;
	Pnew->data=e;
	Q->rear->next=Pnew;
	Q->rear=Pnew;
	return 1;
}
int Pop_Queue(PQueue Q,int *e){
	if(Q->front==Q->rear) return 0;
	*e=Q->front->next->data;
	if(Q->front->next==Q->rear){
		Q->front->next=NULL;
        Q->rear=Q->front;
	}else{
		Q->front->next=Q->front->next->next;
	}
	return 1;
}
int Get_Queue(PQueue Q,int *e){
	if(Q->front==Q->rear) return 0;
	*e=Q->front->next->data;
	return 1;
}
int Print_Queue(PQueue Q){
	PNode P=Q->front->next;
	while(P){
		printf("%d ",P->data);
		P=P->next;
	}
	printf("\n");
}
int main(){
	Queue Q;
	Init_Queue(&Q);
	int e;
	while(scanf("%d",&e)==1){
		if(e==0){
			Pop_Queue(&Q,&e);
		}else{
			Push_Queue(&Q,e);
		}
	}
	if(Empty_Queue(&Q)==1){
		printf("empty\n");
	}else{
		Print_Queue(&Q);
	}
	return 0;
}

2.6.2 运行结果

065260c4aed34c9eb8bdebb3d81fde9d.png

4ef4aaccc5ae4ab99834e0b2e2e46be5.png 

deb7e5f7c9404c74885f1125f2ac70d5.png 

c5982fcc40b54111b1708104ddcfbe78.png  

三、总结

  1.顺序循环队列入队和出队都要考虑“假溢出”的问题

  2.链队列出队时要考虑是否是最后一个有效结点,避免尾结点的丢失

  3.相比之下,链队列不用考虑“假溢出问题”,在实际应用中操作起来跟方便

 

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到