队列的基本操作
- 定义
- 特点
- 储存结构
- 基本运算
- 循环队列的定义与基本操作
- 链队的定义与基本操作
一.定义
队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。队列中没有元素时,称为空队列。
二.特点
队列的特点是先进先出。例如排队付款,先来的人先付款离开,后来的人后付款离开。
三.储存结构
队列按储存结构可分为顺序队列和循环队列
在实现队列的方式上有数值队列,链队。
四.基本运算
序号 | 基本运算 |
---|---|
(1) | 初始化队列:初始条件:队q 不存在。操作结果:构造了一个空队; |
(2) | 入队操作: 初始条件: 队q 存在。操作结果: 对已存在的队列q,插入一个元素x 到队尾,队发生变化; |
(3) | 出队操作: 初始条件: 队q 存在且非空,操作结果: 删除队首元素,并返回其值,队发生变化; |
(4) | 读队头元素:初始条件: 队q 存在且非空,操作结果: 读队头元素,并返回其值,队不变; |
(5) | 判队空操作:初始条件: 队q 存在,操作结果: 若q 为空队则返回为1,否则返回为0; |
五.循环队列的定义与基本操作
在实际使用队列时,为了使队列空间能重复使用,往往对队列的使用方法稍加改进:无论插入或删除,一旦rear指针增1或front指针增1 时超出了所分配的队列空间,就让它指向这片连续空间的起始位置。自己真从MaxSize-1增1变到0,可用取余运算rear%MaxSize和front%MaxSize来实现。这实际上是把队列空间想象成一个环形空间,环形空间中的存储单元循环使用,用这种方法管理的队列也就称为循环队列。除了一些简单应用之外,真正实用的队列是循环队列。 [2]
在循环队列中,当队列为空时,有front=rear,而当所有队列空间全占满时,也有front=rear。为了区别这两种情况,规定循环队列最多只能有MaxSize-1个队列元素,当循环队列中只剩下一个空存储单元时,队列就已经满了。因此,队列判空的条件时front=rear,而队列判满的条件时front=(rear+1)%MaxSize。队空和队满的情况如图:
- 循环队列的初始化
dui * chuang(dui * p)
{//构造一个空队列
p->next=(int *)malloc(maxsize * sizeof( int ));//为队列分配大小为maxsize的数组空间
if(!p->next)//存储分配失败
exit(-1);
p->front=0;//头指针置为0
p->rear=0; //尾指针也置为0 这样表示队列为空
return p;
}
2.循环队列的入队
void ru(dui * p,int x)
{//x为新插入的队尾元素
if((p->rear+1)%maxsize==p->front)//尾指针循环的意义上加一等于头指针表示队列满了
{
printf("队满\n");
exit(0);
}
p->next[p->rear]=x; //新元素插入队尾
p->rear=(p->rear+1)%maxsize; //队尾指针加一
}
3.循环队列的出队
void chu(dui * p,int a)
{//删除对头元素 ,用a返回其值
if(p->front==p->rear) //队列为空
{
printf("队空\n");
exit(-1);
}
a=p->next[p->front];//保存队头元素
p->front=(p->front+1)%maxsize;//队头指针加一
}
4.求循环队列的长度
int length(dui * p)
{//返回p的元素个数就是循环队列的长度
return ((p->rear-p->front+maxsize)%maxsize);
}
5.取循环队列的队头元素
{//返回队头元素
if(p->front!=p->rear)//队列不为空
return p->next[p->front];//返回队头元素,不改变队头指针
else
exit(0);
}
完整代码如下:
#include<stdio.h>
#include<stdlib.h>
#define maxsize 100
typedef struct {
int *next;
int front;
int rear;
}dui;
dui * chuang(dui * p)
{
p->next=(int *)malloc(maxsize * sizeof( int ));
if(!p->next)
exit(-1);
p->front=0;
p->rear=0;
return p;
}
void ru(dui * p,int x)
{
if((p->rear+1)%maxsize==p->front)
{
printf("队满\n");
exit(0);
}
p->next[p->rear]=x;
p->rear=(p->rear+1)%maxsize;
}
void chu(dui * p,int a)
{
if(p->front==p->rear)
{
printf("队空\n");
exit(-1);
}
a=p->next[p->front];
p->front=(p->front+1)%maxsize;
}
int length(dui * p)
{
return ((p->rear-p->front+maxsize)%maxsize);
}
int tou(dui * p)
{
if(p->front!=p->rear)
return p->next[p->front];
else
exit(0);
}
void suoyou(dui * p)
{
while(p->front!=p->rear)
{
printf("%4d",p->next[p->front]);
p->front=(p->front+1)%maxsize;
}
}
int main()
{
int n;
dui * p;
p=chuang(p);
printf("输入要存入队列元素的个数\n");
scanf("%d",&n);
printf("分别输入元素的值\n");
while(n--)
{
int a;
scanf("%d",&a);
ru(p,a);
}
printf("长度为%d\n",length(p));
printf("队头元素为%d\n",tou(p));
printf("队列所有元素为");
suoyou(p);
return 0;
}
运行结果
链队的定义与基本操作
链队定义:所谓队列的链式存储结构是用一个线性链表来表示一个队列,队列中每一个元素对应链表中一个链结点,这样的队列简称链接队列。具体地说,把线性链表第1个链结点的指针定义为队头指针front,在链表最后的链结点建立指针rear作为队尾指针,并且限定只能在链头进行删除操作,在链尾进行插入操作,这个线性链表就构成了一个链接队列。另一个与顺序存储结构队列的不同点是,队头指针与队尾指针都是指向实际队头元素与队尾元素所在的链结点。
1.链队的初始化
li *ch()
{
li *p;
p=(li*)malloc(sizeof(li));
p->front=p->rear=NULL;
return p;
}
2.链队的入队
入队函数我在此处,分了一下情况,所以也就导致后面的输出队头元素的函数有所变化,因为第一次入队,头指针和尾指针都是空指针,必须要对其操作,要不然输出队头指针时,仍然为空指针,无法继续进行操作;(个人想法,有错勿喷)
void shu(li *p,char x)
{
lian *s;
s=(lian*)malloc(sizeof(lian));
s->date=x;
s->next=NULL;
if(p->rear==NULL)
{
p->front=p->rear=s;
}
else
{
p->rear->next=s;
p->rear=s;
}
}
3.链队的出队
void chu(li *p,char a)
{
lian * s;
if(p->rear==NULL)
exit(0);
else
s=p->front;
if(p->front==p->rear)
p->front=p->rear=NULL;
else
{
p->front=p->front->next;
}
a=s->date;
free(s);
}
4.取队头元素
char duitou(li * p)
{
if(p->rear!=NULL)
return p->front->date;
else
exit(0);
}
5.输出链队所以元素
void suoyou(li*p)
{
while(p->front!=NULL)
{
printf("%-4c",p->front->date);
p->front=p->front->next;
}
}
完整代码如下
#include<stdio.h>
#include<stdlib.h>
typedef struct lian
{
char date;
struct lian *next;
}lian;
typedef struct
{
lian *front;
lian *rear;
}li;
li *ch()
{
li *p;
p=(li*)malloc(sizeof(li));
p->front=p->rear=NULL;
return p;
}
void shu(li *p,char x)
{
lian *s;
s=(lian*)malloc(sizeof(lian));
s->date=x;
s->next=NULL;
if(p->rear==NULL)
{
p->front=p->rear=s;
}
else
{
p->rear->next=s;
p->rear=s;
}
}
void chu(li *p,char a)
{
lian * s;
if(p->rear==NULL)
exit(0);
else
s=p->front;
if(p->front==p->rear)
p->front=p->rear=NULL;
else
{
p->front=p->front->next;
}
a=s->date;
free(s);
}
char duitou(li * p)
{
if(p->rear!=NULL)
return p->front->date;
else
exit(0);
}
void suoyou(li*p)
{
while(p->front!=NULL)
{
printf("%-4c",p->front->date);
p->front=p->front->next;
}
}
int main()
{
li *a;
a=ch();
printf("输入要输入队列元素个数\n");
int n;
scanf("%d",&n);
getchar();
printf("输入队列元素\n");
while(n--)
{
char x;
scanf("%c",&x);
shu(a,x);
}
printf("队头元素为%c\n",duitou(a));
printf("链队所有元素为:");
suoyou(a);
return 0;
}
运行结构如图
本文写到的链队可能与你在其他地方看到的不同,尤其是在入队的部分;